Terraform Error Guide: 'Module not installed' run terraform init
Fix Terraform's 'Module not installed' error: run terraform init or terraform get, stop committing .terraform, and add an init step to CI on fresh checkouts.
- #terraform
- #troubleshooting
- #errors
- #modules
Exact Error Message
Terraform refuses to plan or apply because a module block referenced in your configuration has never been installed into the local .terraform/modules directory. The message is explicit about the fix:
Error: Module not installed
on main.tf line 8, in module "vpc":
8: module "vpc" {
This module is not yet installed. Run "terraform init" to install all modules
required by this configuration.
You may also see the shorter inline variant during a validate or plan:
Error: Module not installed: this module is not yet installed. Run "terraform init".
The error always names the file and line of the offending module block, which is the quickest way to know which module Terraform expected to find on disk.
What the Error Means
Terraform separates installation from execution. Before any plan or apply, Terraform must download and record every module declared in your configuration into the local .terraform/modules directory, alongside a manifest at .terraform/modules/modules.json. That installation step happens during terraform init.
When you run terraform plan or terraform apply and Terraform finds a module block in your .tf files that has no matching entry in the modules manifest, it stops immediately with Module not installed. It is purely a local-state problem: Terraform is telling you the working directory has not been initialized for the current set of modules. It is not a network failure, a syntax error, or a provider problem. The configuration is fine; the local .terraform cache is simply out of sync with the code.
This is distinct from Failed to download module, which means Terraform tried to install the module during init but could not fetch it (see Related Errors).
Common Causes
- You ran
plan/applybeforeinit. A brand-new clone or a freshly created working directory has no.terraformdirectory at all, so no modules are installed. - You added a new
moduleblock since the lastinit. Editing the configuration to introduce a module does not install it automatically; Terraform only reads the manifest that existed at the lastinit. .terraform/was deleted or is gitignored on a fresh checkout/CI runner. The standard.gitignoreexcludes.terraform/, so a fresh git checkout or an ephemeral CI runner starts with no installed modules.- The module
sourceorversionchanged. Pointing an existing module block at a new registry version, git ref, or local path invalidates the recorded install. - A clean operation removed the cache. Running
rm -rf .terraform(a common “fix it by nuking it” habit) wipes installed modules until the nextinit.
How to Reproduce the Error
Create a configuration that references a module, then attempt to plan without initializing:
# main.tf
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.8.1"
name = "demo"
cidr = "10.0.0.0/16"
}
# In a fresh directory with no .terraform/
terraform plan
Error: Module not installed
on main.tf line 1, in module "vpc":
1: module "vpc" {
This module is not yet installed. Run "terraform init".
The same happens if you delete the cache on an already-working directory:
rm -rf .terraform
terraform plan # -> Module not installed
Diagnostic Commands
Confirm the module cache is missing or stale before doing anything else:
# Does the modules manifest exist?
ls -la .terraform/modules/modules.json
# What does Terraform think is installed?
cat .terraform/modules/modules.json | jq '.Modules[].Key'
# List every module block your code declares
grep -rn 'module "' *.tf
If modules.json is absent or its keys do not include the module named in the error, the cache is out of sync. You can also ask Terraform to report initialization state:
terraform validate # surfaces "Module not installed" without touching infra
Step-by-Step Resolution
1. Run terraform init. This is the canonical fix and installs every module plus the required providers:
terraform init
Initializing modules...
- vpc in .terraform/modules/vpc
Initializing provider plugins...
Terraform has been successfully initialized!
2. If you only changed module code and want a faster path, run terraform get. It installs modules without re-initializing the backend or providers:
terraform get
3. If you changed a module’s source or version, force an upgrade. Plain init will not always re-resolve a changed constraint; -upgrade re-evaluates module and provider versions:
terraform init -upgrade
4. Never commit .terraform/. Keep it gitignored and treat it as a rebuildable cache, not source of truth:
# .gitignore
.terraform/
*.tfstate
*.tfstate.*
5. Add an explicit init step to CI. Every fresh runner needs to install modules before planning:
# CI pipeline
terraform init -input=false
terraform plan -input=false -out=tfplan
Prevention and Best Practices
- Make
terraform initthe first command in every automation pipeline and every onboarding doc. A working directory is never “ready” until it has been initialized. - Pin module
versionconstraints so aninitis deterministic and reviewers can see exactly what gets installed. - Cache
.terraform/modulesin CI keyed on a hash of your.tffiles and.terraform.lock.hclto speed up repeat runs without committing the directory. - After any pull that touches
moduleblocks, runterraform init(orterraform get) before planning to resync the cache. - Use
terraform init -upgradedeliberately when bumping module versions, and commit the resulting.terraform.lock.hcl. - For a quick triage of init-time failures, the free incident assistant can tell
Module not installed(local cache) apart fromFailed to download module(fetch failure). More patterns live in the Terraform guides.
Related Errors
Failed to download module— Terraform tried to install the module duringinitbut could not fetch the source (bad source address, git auth, missing ref, network/proxy). Ifinititself errors instead ofplan, see the Failed to download module guide.Initialization required/Backend initialization required— a sibling message when the backend, not the modules, is uninitialized; the fix is stillterraform init.Module not installedafterterraform statecommands — state subcommands also require an initialized directory; runinitfirst.Provider configuration not present— a different sync problem where a provider, not a module, is missing from the lock file.
Frequently Asked Questions
Why does terraform plan not just install the module for me?
By design, Terraform keeps installation (init/get) separate from execution (plan/apply) so that runs are reproducible and side-effect-free. plan reads the existing module manifest but never downloads anything, so it errors instead of silently fetching code.
Do I need to re-run init every time, or only sometimes?
Only when the installed set changes: a fresh checkout, a new or changed module block, a deleted .terraform, or a new provider/version. On an unchanged, already-initialized directory you can plan and apply repeatedly without re-running init.
Should I commit the .terraform/modules directory to make CI faster?
No. Commit the .terraform.lock.hcl file (for provider/module reproducibility) but keep .terraform/ gitignored. For speed, use your CI’s caching mechanism keyed on the lock file rather than version-controlling the cache.
What is the difference between terraform init and terraform get?
terraform get installs only modules. terraform init installs modules and providers, configures the backend, and writes the dependency lock file. Use get for a quick module-only resync; use init for everything else.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.