Quick Answer
You’re referencing a resource that doesn’t exist in your configuration. Check for:
- Typo in the resource name
- Missing resource block
- Wrong module reference (need
module.name.output) - Resource in a different workspace/state
The Error
Error: Reference to undeclared resource
on main.tf line 8, in resource "aws_subnet" "public":
8: vpc_id = aws_vpc.main.id
A managed resource "aws_vpc" "main" has not been declared in the root module.
Cause 1: Typo in Resource Name
resource "aws_vpc" "primary" { # Named "primary"
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id # ❌ Referencing "main" — doesn't exist!
}
Fix
resource "aws_subnet" "public" {
vpc_id = aws_vpc.primary.id # ✅ Match the actual resource name
}
Cause 2: Resource Doesn’t Exist Yet
You’re referencing a resource you haven’t created:
resource "aws_instance" "web" {
ami = "ami-abc123"
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.web.id] # ❌ No such resource
}
# Missing: aws_security_group.web
Fix
Create the missing resource:
resource "aws_security_group" "web" {
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
ami = "ami-abc123"
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.web.id] # ✅ Now exists
}
Cause 3: Wrong Module Reference
module "networking" {
source = "./modules/networking"
}
resource "aws_instance" "web" {
# ❌ Can't reference resources inside a module directly
subnet_id = aws_subnet.public.id
}
Fix
Use module outputs:
# In modules/networking/outputs.tf
output "public_subnet_id" {
value = aws_subnet.public.id
}
# In root module
resource "aws_instance" "web" {
subnet_id = module.networking.public_subnet_id # ✅ Use module output
}
Cause 4: Data Source vs Resource Reference
data "aws_vpc" "existing" {
filter {
name = "tag:Name"
values = ["production"]
}
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.existing.id # ❌ Missing "data." prefix
}
Fix
resource "aws_subnet" "public" {
vpc_id = data.aws_vpc.existing.id # ✅ Add "data." prefix
}
Cause 5: Resource Behind count or for_each
resource "aws_instance" "web" {
count = var.create_web ? 1 : 0
ami = "ami-abc123"
instance_type = "t3.micro"
}
resource "aws_eip" "web" {
instance = aws_instance.web.id # ❌ Must include index when count is used
}
Fix
resource "aws_eip" "web" {
count = var.create_web ? 1 : 0
instance = aws_instance.web[0].id # ✅ Include index
# Or use conditional
instance = var.create_web ? aws_instance.web[0].id : null
}
For for_each:
resource "aws_instance" "web" {
for_each = toset(["a", "b"])
ami = "ami-abc123"
instance_type = "t3.micro"
}
# ❌ Must specify which instance
output "ip" {
value = aws_instance.web.public_ip
}
# ✅ Specify the key
output "ip_a" {
value = aws_instance.web["a"].public_ip
}
# ✅ Or get all
output "ips" {
value = { for k, v in aws_instance.web : k => v.public_ip }
}
Cause 6: Resource in Different File Was Deleted
If you recently refactored and moved resources between files:
# Check if the resource exists anywhere
grep -r 'resource "aws_vpc" "main"' *.tf
grep -r 'resource "aws_vpc" "main"' modules/
Cause 7: Terraform Cloud/Workspaces
The resource might be in a different workspace or state file:
# Use data source to read from another state
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "tf-state"
key = "networking/terraform.tfstate"
region = "us-east-1"
}
}
resource "aws_instance" "web" {
subnet_id = data.terraform_remote_state.networking.outputs.subnet_id
}
Debugging
# Validate configuration
terraform validate
# List all resources in current state
terraform state list
# Search for resource across files
grep -rn 'resource "aws_vpc"' .
Hands-On Courses
- Terraform for Beginners on CopyPasteLearn
- Terraform By Example — practical code examples
Conclusion
“Reference to undeclared resource” means Terraform can’t find the resource you’re pointing to. The most common causes are typos in resource names, missing data. prefix for data sources, missing module. prefix for module outputs, and forgetting to include [0] or ["key"] when using count or for_each. Run terraform validate to catch these errors early.
