Quick Answer
# Check for typos
grep -rn 'resource "aws_instance"' *.tf
# For module resources, use module.NAME.OUTPUT
module.networking.vpc_id # ✅
aws_vpc.main.id # ❌ (if vpc is in a module)
The Error
Error: Reference to undeclared resource
on main.tf line 12, in resource "aws_instance" "web":
12: subnet_id = aws_subnet.public.id
A managed resource "aws_subnet" "public" has not been declared in the
root module.
What Causes This
- Typo —
aws_subnet.publcinstead ofaws_subnet.public - Resource is in a module — can’t reference module internals directly
- Resource was deleted — someone removed the resource block
- Wrong resource type —
aws_subnetvsaws_default_subnet - Resource defined in another file — but that file has a syntax error preventing loading
Solution 1: Fix Typos
# ❌ Typo in resource name
subnet_id = aws_subnet.publc.id
# ✅ Correct name
subnet_id = aws_subnet.public.id
# Find all resource declarations
grep -rn 'resource "aws_subnet"' *.tf
Solution 2: Cross-Module References
Resources inside a module can’t be referenced directly. Use outputs:
# ❌ Can't reach inside a module
subnet_id = module.networking.aws_subnet.public.id
# ✅ Use module output
subnet_id = module.networking.public_subnet_id
The module must declare the output:
# modules/networking/outputs.tf
output "public_subnet_id" {
value = aws_subnet.public.id
}
Solution 3: Check Resource Exists
# List all resources in all .tf files
grep -rn '^resource "' *.tf modules/**/*.tf
# List resources in state
terraform state list | grep subnet
Solution 4: File-Level Syntax Errors
If a .tf file has a syntax error, Terraform can’t load any resources from it:
terraform validate
# May show: Error in networking.tf line 5 — fixing this may resolve the undeclared reference
Solution 5: Data Sources vs Resources
# ❌ Wrong prefix
subnet_id = aws_subnet.existing.id # This is a resource reference
# ✅ Use data source prefix
subnet_id = data.aws_subnet.existing.id # This is a data source reference
data "aws_subnet" "existing" {
filter {
name = "tag:Name"
values = ["my-subnet"]
}
}
resource "aws_instance" "web" {
subnet_id = data.aws_subnet.existing.id # Note: data. prefix
}
Common Patterns
Referencing Across Files
Within the same module, resources can reference each other across files:
# vpc.tf
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
# subnets.tf — can reference vpc.tf resources
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id # ✅ Works across files in same module
}
Referencing count/for_each Resources
resource "aws_subnet" "public" {
count = 3
# ...
}
# Reference specific index
subnet_id = aws_subnet.public[0].id
# Reference all
subnet_ids = aws_subnet.public[*].id
Hands-On Courses
- Terraform for Beginners on CopyPasteLearn
- Terraform By Example — practical code examples
Conclusion
“Reference to undeclared resource” usually means a typo or a cross-module reference problem. Check spelling with grep, use module outputs for cross-module references, and don’t forget the data. prefix for data sources. Run terraform validate to catch syntax errors in other files that might prevent resource loading.