Fix Terraform "Error: Reference to undeclared output value" โ€” Module Output Not Found

intermediate๐Ÿ—๏ธ Terraform2026-03-22| Terraform CLI 1.x, any provider, Linux/macOS/Windows

Error Message

Error: Reference to undeclared output value
#terraform#output#reference#variable#syntax

The Situation

It's late. You're wiring up a new module to pass its VPC ID or ARN to another resource, you run terraform plan, and get slapped with this:

Error: Reference to undeclared output value

  on main.tf line 14, in resource "aws_instance" "app":
  14:   subnet_id = module.network.subnet_id

An output value with the name "subnet_id" has not been declared in module.network.

The module exists. The resource exists. Yet Terraform won't budge โ€” it can't find the output you're trying to read.

Why This Happens

Terraform modules are black boxes. The only values they expose to the outside world are those explicitly declared in an output block inside the module. When you reference module.network.subnet_id, Terraform looks for an output "subnet_id" block in the network module directory. No block, no value โ€” just this error.

A few things cause this:

  • You added a reference in the calling module but forgot to declare the output block in the child module.
  • You renamed an output block but didn't update all the places that reference it.
  • You copied a module from somewhere else and the outputs you expected don't exist in this version.
  • There's a subtle name mismatch โ€” subnet_ids (plural) vs. subnet_id (singular), for example.
  • You're pulling outputs across workspaces via terraform_remote_state, and that output was never declared in the source stack.

Step 1 โ€” See What Outputs the Module Actually Declares

Start by finding where the module lives. For a local module, the error message tells you โ€” module.network means look in modules/network/:

ls modules/network/
grep -r 'output' modules/network/

For a registry or Git-sourced module, check the cached download:

find .terraform/modules -name '*.tf' | xargs grep '^output'

You'll see every output block the module actually has. Compare that list against what you're referencing โ€” the mismatch will jump out.

Add the Missing Output Block

If you control the module, the fix is straightforward. Add the output inside the module directory โ€” typically modules/network/outputs.tf:

output "subnet_id" {
  description = "The ID of the primary subnet"
  value       = aws_subnet.main.id
}

Run terraform plan again. Error gone.

Need to expose multiple subnets? Use a list output instead:

output "subnet_ids" {
  description = "List of all subnet IDs"
  value       = aws_subnet.main[*].id
}

Then index into it from the calling config:

subnet_id = module.network.subnet_ids[0]

The Output Exists โ€” But Under a Different Name

Before editing anything, check what the module actually exposes. The Terraform console is useful here:

terraform console
> module.network

That prints all available outputs from the module. Nine times out of ten you'll spot a naming mismatch immediately โ€” then just update the reference:

# Wrong
subnet_id = module.network.subnet_id

# Right โ€” output block is named "private_subnet_id"
subnet_id = module.network.private_subnet_id

Remote State: Output Missing From the Source Stack

Using terraform_remote_state to read outputs from another workspace? The output must be declared โ€” and applied โ€” in the source stack first.

data "terraform_remote_state" "vpc" {
  backend = "s3"
  config = {
    bucket = "my-tf-state"
    key    = "vpc/terraform.tfstate"
    region = "us-east-1"
  }
}

resource "aws_instance" "app" {
  subnet_id = data.terraform_remote_state.vpc.outputs.subnet_id
}

The VPC stack needs this in its outputs.tf:

output "subnet_id" {
  value = aws_subnet.main.id
}

Deploy the VPC stack first. Terraform reads from the state file โ€” if the output was never applied, it won't be there. Having it in a .tf file isn't enough.

Public Registry Module: Version Doesn't Have That Output

Pinning to an older module version? The output might not exist yet. This is common with terraform-aws-modules โ€” version 3.x and 5.x expose different outputs.

module "network" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.0.0"  # missing the output you need
}

Check the module's changelog or browse its outputs.tf on GitHub for that specific tag. If a newer version has what you need, bump it:

module "network" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.1.0"
}

Then pull the update:

terraform init -upgrade

Verify the Fix

Run these three commands in order:

# Catch any syntax issues first
terraform validate

# Should complete with no errors
terraform plan

# See all root-level outputs after apply
terraform output

Want to confirm a specific module reference before applying? Use the console:

terraform console
> module.network.subnet_id

If it returns a value (or a known placeholder), the reference is wired up correctly.

Quick Reference

  • Output declared in wrong file โ€” Doesn't matter which .tf file inside the module holds the output block, as long as it's somewhere in the module directory.
  • Sensitive outputs โ€” Marking an output sensitive = true doesn't break references. Terraform just redacts the value in plan output.
  • Modules using count or for_each โ€” The output shape changes. Reference it as module.network[0].subnet_id instead of module.network.subnet_id.

Related Error Notes