Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 9 min read

Terraform Error Guide: 'Reference to undeclared input variable' (missing or mistyped variable declarations)

Fix Terraform's Reference to undeclared input variable error caused by typos, a missing variables.tf, renames, or module-scoped variables.

  • #terraform
  • #troubleshooting
  • #errors
  • #variables

Exact Error Message

When you reference a var.something that Terraform cannot find a matching declaration for, the run halts before any planning happens. The error looks like this:

Error: Reference to undeclared input variable

  on main.tf line 9, in resource "aws_instance" "web":
   9:   instance_type = var.instnce_type

An input variable with the name "instnce_type" has not been declared. This
variable can be declared with a variable "instnce_type" {} block.

The message always names the file, the line, the resource (or output, local, etc.) where the reference lives, and the exact variable name Terraform looked for. That last detail is the key to fixing it quickly.

What the Error Means

Terraform builds a graph of every value you reference. When it encounters var.instnce_type, it looks for a variable "instnce_type" {} block in the same module. If no such block exists, Terraform cannot resolve the reference and stops.

The two words that trip people up most are input and the implicit word module. A var. reference resolves only against variable declarations in the current module’s directory. Variables are not global. A variable "region" {} block declared in a child module is completely invisible to the root module, and vice versa. Each module has its own private namespace for variables.

So this error means one of two things: the declaration genuinely does not exist, or it exists somewhere Terraform is not looking (a different module).

Common Causes

1. A typo in the variable name. var.instnce_type instead of var.instance_type. This is the single most common cause. The error message echoes the misspelled name back to you, so compare it carefully against your declarations.

2. The variable is declared in a different module. Variables are module-scoped. If variable "instance_type" {} lives in modules/ec2/variables.tf and you reference var.instance_type from the root main.tf, the root module has no such variable.

3. A missing variables.tf in the module. If you copied resources into a new module directory but forgot to bring the variables.tf file along, every var. reference in that directory becomes undeclared.

4. A renamed variable. You renamed variable "ami_id" to variable "image_id" but a resource, output, or local still references the old var.ami_id.

5. A child-module variable that was never declared. Inside a child module you reference var.subnet_id, but you forgot to add a variable "subnet_id" {} block to that module. Passing subnet_id = ... in the parent module block is not enough; the child must declare it to receive it.

6. Confusing var. with local. or module.. You wrote var.vpc_id when the value is actually a local (local.vpc_id) or a module output (module.network.vpc_id). These are three different namespaces.

How to Reproduce the Error

Create a tiny config with a deliberate typo:

# main.tf
variable "instance_type" {
  type    = string
  default = "t3.micro"
}

resource "aws_instance" "web" {
  ami           = "ami-0abcd1234"
  instance_type = var.instnce_type   # typo: missing the second "a"
}

Run terraform validate and Terraform reports the undeclared variable on the resource line. You can reproduce the module-scope variant by declaring instance_type only inside modules/ec2/variables.tf while referencing var.instance_type from the root module.

Diagnostic Commands

All of these are read-only and safe to run repeatedly. None of them change state.

Validate the configuration to surface every undeclared reference at once:

terraform validate

List every variable declaration in the current module directory:

grep -rn 'variable "' .

Search for every place a specific variable is referenced so you can spot the mismatch:

grep -rn 'var\.instnce_type' .

Confirm a variables.tf actually exists in the module you are running from:

ls -la
find . -name 'variables.tf'

Inspect the declared variables interactively without applying anything:

terraform console
> var.instance_type
"t3.micro"
> var.instnce_type
Error: Reference to undeclared input variable

A clean terraform validate plus a terraform plan (which is read-only against your infrastructure) confirms the fix. Never reach for apply, destroy, or state rm to diagnose this — it is purely a configuration-resolution error and a state change cannot fix it.

Step-by-Step Resolution

Step 1: Read the error precisely. Note the file, line, and the exact variable name Terraform quotes. That name is what it searched for and failed to find.

Step 2: Confirm which module directory you are in. Run terraform validate from the directory that produced the error. Remember that each directory of .tf files is its own module with its own variable namespace.

Step 3: List the declarations in that directory. Run grep -rn 'variable "' .. If the variable name you need is absent, you have a missing declaration. If it is present but spelled differently, you have a typo.

Step 4a (typo). Fix the spelling at the reference site so it matches the declaration exactly:

instance_type = var.instance_type

Step 4b (missing declaration). Add the variable block to the module’s variables.tf (create the file if it does not exist):

# variables.tf
variable "instance_type" {
  type        = string
  description = "EC2 instance size"
  default     = "t3.micro"
}

Step 4c (wrong module / child module). If the value lives in another module, do not try to reference it directly across the boundary. In the child module, declare the variable; in the parent, pass it through the module block:

# modules/ec2/variables.tf
variable "instance_type" {
  type = string
}

# root main.tf
module "ec2" {
  source        = "./modules/ec2"
  instance_type = "t3.large"   # passed in to the child module
}

Step 4d (wrong namespace). If the value is actually a local or a module output, change the prefix:

instance_type = local.instance_type        # for a locals block
subnet_id     = module.network.subnet_id   # for a child module output

Step 5: Re-validate. Run terraform validate, then terraform plan, and confirm the error is gone.

Prevention and Best Practices

Keep a variables.tf in every module directory, even small ones, so declarations have a predictable home. Use terraform fmt and an editor with HCL language support so misspelled var. references are flagged as you type.

Run terraform validate in CI on every pull request — it catches undeclared variables before they ever reach a plan or apply. Adopt a consistent naming convention (snake_case, no abbreviations like instnce) to reduce typos. When you rename a variable, immediately grep -rn 'var\.old_name' . to find and update every reference.

Most importantly, internalize that variables are module-local. Treat each module as a function with an explicit input signature: the only way data enters a child module is through declared variable blocks plus values passed in the parent’s module block. If validation feels noisy in a busy pipeline, route Terraform CI failures through an automated triage layer like the incident response workflow so undeclared-variable errors get grouped and explained automatically.

For more Terraform troubleshooting guides, browse the Terraform category.

Frequently Asked Questions

Why does Terraform say a variable is undeclared when I clearly declared it in another file? Variables are resolved per module directory, not per file. As long as the variable block is in a .tf file in the same directory you are running from, file name does not matter. But a declaration in a different module directory is invisible — that is the most common false “I declared it” case.

Can a child module use a variable declared in the parent module? No. Each module has its own variable namespace. The child must declare its own variable block, and the parent passes a value through the module block. There is no inheritance or global scope for variables.

What is the difference between var., local., and module.? var.x reads an input variable declared with a variable block. local.x reads a value from a locals block. module.name.output reads an output exported by a child module. Mixing these prefixes is a frequent cause of this error.

Will terraform validate always catch this before apply? Yes. Undeclared variable references are static configuration errors, so validate (and plan) detect them without touching any real infrastructure. There is no need to apply to surface or fix the problem.

I renamed a variable and now get this error — what is the fastest fix? Run grep -rn 'var\.old_name' . to list every stale reference, update each to the new name, then re-run terraform validate. The grep ensures you do not miss references hiding in outputs or locals.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.