This error occurs when Terraform tries to reference a module that hasn't been declared in the current configuration scope. Learn how to properly declare modules and pass values between them.
Terraform modules have their own scope. When you try to reference a module like `module.networking.vpc_id` without declaring that module in your current configuration, Terraform cannot find it. This typically happens when: 1. A module block hasn't been declared in the calling configuration 2. A module in one scope tries to reference a sibling module directly 3. The module name doesn't match the declaration exactly (case-sensitive) 4. Module files haven't been initialized yet Unlike global variables, Terraform modules must be explicitly declared and their outputs explicitly referenced through the module.LABEL.OUTPUT syntax.
Check that you have a module block declaring the module you're trying to reference. For example, if referencing module.networking, you must have declared it:
module "networking" {
source = "./modules/networking"
# ... other configuration
}Ensure the label (name after module) matches exactly what you're referencing elsewhere.
Module names are case-sensitive in Terraform. If your declaration uses module "Networking" but you reference module.networking, it won't work.
Double-check:
- Spelling of the module name
- Capitalization
- Special characters
The label between module "" and the reference must match exactly.
If you have a child module that needs to reference another module's output, you must pass it through the parent (root) module:
In root main.tf:
module "networking" {
source = "./modules/networking"
}
module "security" {
source = "./modules/security"
vpc_id = module.networking.vpc_id # Pass output as input
}In modules/security/variables.tf:
variable "vpc_id" {
description = "VPC ID from networking module"
type = string
}This way, the security module receives the value as a variable instead of trying to reference the networking module directly.
After declaring new modules, initialize them:
terraform initThis downloads and prepares all declared modules. If you've recently added module blocks but haven't run init, the modules won't be available.
Use terraform validate to check for syntax errors and scope issues:
terraform validateThis will catch many undeclared module references before you attempt a plan or apply.
If you're working with a single root configuration file that references multiple modules, all module blocks must be in the same file or included via Terraform's configuration merging (same directory).
Example structure:
.
├── main.tf # Contains module blocks
├── variables.tf # Input variables
├── outputs.tf # Outputs
└── modules/
├── networking/
└── security/All module "..." blocks must be in the root configuration files (main.tf, modules.tf, etc.) at the same level.
Module scope in Terraform is hierarchical. The root module is the entry point, and each child module has its own scope. You cannot directly reference sibling modules from within a child module—only parent-declared modules. If you need values from multiple sources in a child module, they must all be passed as input variables from the parent. For complex scenarios, consider using for_each loops with modules or conditional module creation using count/for_each to manage interdependencies more cleanly.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform