Error: Reference to undeclared resource: "has not been declared in the root module"
Fixes Terraform's "Error: Reference to undeclared resource ... has not been declared in the root module", caused by typos, renames, or referencing resources across module boundaries. Use when plan or validate fails on a resource name that looks right. Not for "Unsupported attribute" (resource exists, attribute does not).
TL;DR
You referenced a resource name that does not exist in the module where the reference lives. It is almost always a typo, a rename you forgot to propagate, or a reference to something declared in a different module. Fix the name to match the declared resource, then terraform validate.
The error
Error: Reference to undeclared resource
on outputs.tf line 3, in output "vpc_id":
3: value = aws_vpc.main.id
A managed resource "aws_vpc" "main" has not been declared in the root module.Steps to fix
- Open the file and line the error names. Copy the exact resource address it complains about (
aws_vpc.main).
- Expected: you have the type and name Terraform looked for.
- Search your configuration for the resource block:
grep -rn 'resource "aws_vpc"' *.tf. Compare the declared name with the referenced name.
- Expected: you spot the typo or the rename (e.g. declared
aws_vpc.this, referencedaws_vpc.main).
- Fix the reference (or the declaration, whichever is wrong). If the resource lives in a child module, you cannot reference it directly: add a module output and use
module.[name].[output].
- Expected: every reference matches a declared address.
- Run
terraform validate.
- Expected:
Success! The configuration is valid.
When to use this
terraform planorvalidatefails withReference to undeclared resourceright after you renamed something, copied config between files, or split config into modules.
When NOT to use this
Unsupported attributemeans the resource exists but the attribute does not.Reference to undeclared variable/local valueare the variable/local equivalents, fixed the same way.
Compatibility
- All Terraform versions 0.12+. Module scoping rules are unchanged across 1.x.
Root cause
Terraform resolves every reference against the declarations in the same module. A resource in a child module is invisible to the root module (and vice versa); only outputs cross that boundary. Renames break references because addresses are type+name pairs, and nothing auto-updates them.
Edge cases
count = 0resources still count as declared; the reference resolves but the value may be an empty tuple. Useone()ortry()instead of[0].- Data sources use
data.[type].[name]: forgetting thedata.prefix gives this error. - After
terraform state mv, config references do not change; this error means the config itself is wrong, not the state.
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.