Error: Module not installed
Fixes terraform's "Error: Module not installed" failure. Use when plan or apply fails right after adding a module block, changing its source, or on a fresh clone. Explains why re-running terraform init is required. Not for module registry resolution errors or backend init failures.
Fix terraform "Error: Module not installed"
TL;DR: You added a module block, or changed a module's source, after the last terraform init. Module installation happens only during init; plan never installs. Run terraform init again, and re-run it every time you touch a module block.
The error
Error: Module not installed
on main.tf line 11, in module "ada":
11: module "ada" {
This module is not yet installed. Run "terraform init" to install all modules required by this configuration.Steps
- Run
terraform init. Expected: output shows the new module being installed into.terraform/modules, ending withTerraform has been successfully initialized! - If you changed a
source(new registry version, new git ref), runterraform init -upgradeso the cached copy is refreshed. Expected: the module is re-downloaded at the new source. - Verify the install manifest: check
.terraform/modules/modules.jsonlists your module. Expected: it is there. - Run
terraform plan. Expected: the plan proceeds instead of erroring.
When this applies
planorapplyfails with "Module not installed" right after you added a module block, changed itssource, or cloned the repo fresh.- CI pipelines that run
planwithout aninitstage fail the first time anyone adds a module.
When it does NOT apply
- Registry resolution errors for a module source ("module not found"). That is a source-address problem, not a missed init.
- Backend initialization errors. Those are about state storage, not module code.
Tool and version compatibility
- All Terraform CLI versions. The init-installs-modules rule predates 0.12 and is unchanged.
Why it happens
init copies or links each child module into .terraform/modules and records it in the manifest. plan and apply only read that manifest; they never fetch. A module block added after init is simply unknown to the working directory until init runs again.
Edge cases and pitfalls
- Changing only the module's
versionor gitrefstill requires re-init; the cached copy is pinned to the old one. - Every CI pipeline needs a dedicated
terraform init -input=falsestage before plan. It is cheap and idempotent, and it also downloads any new providers the module pulls in.