Fix Terraform 'Module not installed' Error When Running Plan Without terraform init

beginner๐Ÿ—๏ธ Terraform2026-03-26| Terraform 0.13+, any OS (Linux, macOS, Windows), local or CI/CD pipelines

Error Message

Error: Module not installed This module is not yet installed. Run "terraform init" to install all modules required by this configuration.
#terraform#init#module#provider

TL;DR

Run terraform init in your working directory before running terraform plan or terraform apply. That's it.

terraform init
terraform plan

Already ran init in CI/CD but still hitting this? Jump to the deeper causes section below.

The Error

Error: Module not installed

This module is not yet installed. Run "terraform init" to install all modules required by this configuration.

Terraform throws this when it finds a module block in your .tf files but can't locate the downloaded source under .terraform/modules/. The module metadata isn't there yet โ€” so Terraform stops before doing anything else.

Root Cause

Say you have a module block like this:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.1.2"

  name = "my-vpc"
  cidr = "10.0.0.0/16"
}

Before Terraform can evaluate that block, it needs the actual module source on disk. The terraform init command handles that fetch. It writes to two places:

  • .terraform/modules/ โ€” the downloaded module files
  • .terraform/modules/modules.json โ€” registry metadata

No .terraform/modules/ directory? Terraform bails immediately. This happens when plan runs before init, or when someone deleted .terraform/ without reinitializing.

The most common triggers:

  • Fresh repo clone โ€” .terraform/ is gitignored (correctly), so it's never committed
  • CI/CD pipeline where the init step was skipped or failed silently
  • New module block added but init wasn't re-run
  • Someone ran rm -rf .terraform/ to clean up and forgot to reinitialize
  • Branch switch where a different module source or version is declared

Fix Approaches

Approach 1 โ€” Standard fix (local development)

# Navigate to the Terraform working directory
cd path/to/your/terraform

# Initialize โ€” downloads modules and providers
terraform init

# Now plan works
terraform plan

Approach 2 โ€” Added a new module to existing config

Added a new module block to an already-initialized workspace? Re-run init to pull in the new source:

terraform init -upgrade

The -upgrade flag isn't strictly required (plain init works fine), but it's a good habit โ€” it also bumps providers to their latest allowed versions within your declared constraints.

Approach 3 โ€” CI/CD pipelines

In GitHub Actions, GitLab CI, or similar, keep init and plan as explicit separate steps:

# GitHub Actions example
- name: Terraform Init
  run: terraform init
  working-directory: ./infra

- name: Terraform Plan
  run: terraform plan
  working-directory: ./infra

Running a remote backend (S3, GCS, Terraform Cloud)? Pass backend config explicitly โ€” otherwise init can fail silently on missing credentials and your pipeline moves on anyway:

terraform init \
  -backend-config="bucket=my-tf-state" \
  -backend-config="key=prod/terraform.tfstate" \
  -backend-config="region=us-east-1"

Approach 4 โ€” Module from local path not found

Local path modules work differently than registry ones. Check the declaration:

module "networking" {
  source = "../modules/networking"
}

That path must exist relative to the calling module. A typo here causes init to fail โ€” and a failed init means plan throws this same error. Verify before re-running:

# Confirm the path resolves
ls ../modules/networking

# Then reinitialize
terraform init

Approach 5 โ€” Working directory mismatch

This one catches people in monorepos. Running init and plan from different directories is the culprit โ€” each directory needs its own .terraform/:

# Wrong โ€” init ran in /infra, plan runs from /
cd /infra && terraform init
cd / && terraform plan   # โ† fails, no .terraform here

# Correct โ€” both commands in the same directory
cd /infra
terraform init
terraform plan

Verification

Once init finishes, confirm the modules landed correctly:

# Check the modules directory exists and has content
ls .terraform/modules/

# Should show modules.json plus a directory for each module
# Example output:
# modules.json  vpc/

Run terraform plan. It should sail past the module loading stage and print either a resource diff or the familiar "No changes" message:

terraform plan

# Successful output starts with:
# Terraform used the selected providers to generate the following execution plan...

Prevention Tips

  • Keep .terraform/ in .gitignore โ€” it's in Terraform's official template, but older repos sometimes have it missing. Worth a quick check.
  • Add a one-liner to your repo README: "Run terraform init after cloning." Saves every new contributor from hitting this.
  • In CI/CD, treat init and plan as separate named steps. When something breaks, you'll know immediately which step failed.
  • Working with deeply nested modules and a messy .terraform.lock.hcl? Paste the lock file content into ToolCraft's YAML โ†” JSON converter to quickly spot structural issues โ€” HCL's key-value syntax is close enough that a converter flags mismatched brackets and malformed blocks that are easy to miss by eye.

Quick Reference

# Always run init first
terraform init

# Re-run init after adding or changing modules
terraform init

# Upgrade providers and modules to latest allowed versions
terraform init -upgrade

# Verify modules are installed
ls .terraform/modules/
cat .terraform/modules/modules.json

Related Error Notes