Fix Terraform Undeclared Variable Errors

Tested on Ubuntu 26.04 LTS (Resolute Raccoon)
Package terraform 1.15.8-1
Applies to Any host with Terraform installed
Lab environment Single Ubuntu VM with Terraform — Terraform lab environment on Ubuntu
Privilege Normal user
Scope Troubleshooting Terraform undeclared variable errors — Reference to undeclared input variable versus Value for undeclared variable, missing variable blocks, extra terraform.tfvars keys, -var and -var-file mistakes, root versus child module scope, name diagnostics, and validate-plan verification. Does not cover full input-variable precedence across CLI, env, and HCP layers.
Related guides Terraform variables
Terraform module input and output
terraform validate
terraform plan
Terraform troubleshooting

Terraform reports undeclared variable problems in two different shapes. The fix depends on which message you see:

text
Reference to undeclared input variable

versus:

text
Value for undeclared variable

The first means configuration references var.something that was never declared in that module. The second means a value arrived from terraform.tfvars, -var, or -var-file for a name the module does not know about.

Each scenario uses its own directory under ~/terraform-labs/terraform-undeclared-variable-error/. Examples use built-in terraform_data only.

NOTE
Run terraform init in module directories before validate or plan. This article does not walk the full variable precedence ladder — see Terraform variables when multiple assignment sources disagree.

Two undeclared variable error types

Message What happened Typical source
Reference to undeclared input variable HCL uses var.name with no matching variable block main.tf, module argument, expression
Value for undeclared variable A value was assigned to a name the module never declared terraform.tfvars, -var, -var-file

Extra tfvars keys surface as a warning when plan loads the assignment file. Wrong -var names fail at plan time with an error, often paired with No value for required variable, because the CLI assignment is evaluated when Terraform binds input variables for that run.


Fix a missing variable block

Configuration references var.environment but no variable block exists yet.

bash
mkdir -p ~/terraform-labs/terraform-undeclared-variable-error/errors/missing-declaration
cd ~/terraform-labs/terraform-undeclared-variable-error/errors/missing-declaration

Write the broken configuration:

bash
cat > main.tf <<'EOF'
terraform {
  required_version = ">= 1.12.0"
}

resource "terraform_data" "label" {
  input = "env-${var.environment}"
}
EOF

validate stops on the undeclared reference before plan can run:

bash
terraform validate -no-color
output
Error: Reference to undeclared input variable

  on main.tf line 6, in resource "terraform_data" "label":
   6:   input = "env-${var.environment}"

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

Add a declaration in variables.tf:

hcl
variable "environment" {
  type = string
}

The fixed tree lives in fixes/missing-declaration/. Move there first:

bash
cd ~/terraform-labs/terraform-undeclared-variable-error/fixes/missing-declaration

The new variable block should clear validation:

bash
terraform validate -no-color
output
Success! The configuration is valid.

Supply the variable on the command line:

bash
terraform plan -no-color -input=false -var='environment=prod'
output
Plan: 1 to add, 0 to change, 0 to destroy.

  # terraform_data.label will be created
  + resource "terraform_data" "label" {
      + input = "env-prod"
    }

The reference and the declaration now share the same name in the same module scope.


Fix tfvars with an undeclared variable

A terraform.tfvars key does not create a variable — it only assigns one that already exists.

bash
mkdir -p ~/terraform-labs/terraform-undeclared-variable-error/errors/extra-tfvars
cd ~/terraform-labs/terraform-undeclared-variable-error/errors/extra-tfvars

Declare only name but assign environment in tfvars:

bash
cat > main.tf <<'EOF'
resource "terraform_data" "label" {
  input = var.name
}
EOF

Add the lone declared variable in variables.tf:

bash
cat > variables.tf <<'EOF'
variable "name" {
  type = string
}
EOF

The extra environment key lives in terraform.tfvars:

bash
cat > terraform.tfvars <<'EOF'
name        = "demo"
environment = "prod"
EOF

Terraform accepts the configuration itself, but when plan loads terraform.tfvars it warns that environment was assigned even though the root module never declared that variable:

bash
terraform plan -no-color -input=false
output
Plan: 1 to add, 0 to change, 0 to destroy.

  # terraform_data.label will be created
  + resource "terraform_data" "label" {
      + input = "demo"
    }

Warning: Value for undeclared variable

The root module does not declare a variable named "environment" but a value
was found in file "terraform.tfvars". If you meant to use this value, add a
"variable" block to the configuration.

Either remove the stray key from terraform.tfvars or declare environment and use it. The fix in fixes/extra-tfvars/ adds:

hcl
variable "environment" {
  type = string
}

and changes the resource input to "${var.name}-${var.environment}". After that, plan shows input = "demo-prod" with no undeclared-variable warning.


Fix -var and -var-file errors

When the variable block exists but the CLI name is wrong, Terraform reports Value for undeclared variable for the mistyped name and No value for required variable for the real one.

bash
mkdir -p ~/terraform-labs/terraform-undeclared-variable-error/errors/wrong-cli-var
cd ~/terraform-labs/terraform-undeclared-variable-error/errors/wrong-cli-var

Required sensitive variable with no default:

bash
cat > main.tf <<'EOF'
resource "terraform_data" "label" {
  input = var.api_token
}
EOF

Declare the sensitive token variable separately:

bash
cat > variables.tf <<'EOF'
variable "api_token" {
  type      = string
  sensitive = true
}
EOF

Hyphens are not underscores — api-token is a different name:

bash
terraform plan -no-color -input=false -var='api-token=secret'
output
Error: Value for undeclared variable

A variable named "api-token" was assigned on the command line, but the root
module does not declare a variable of that name. To use this value, add a
"variable" block to the configuration.

Error: No value for required variable

  on variables.tf line 1:
   1: variable "api_token" {

The root module input variable "api_token" is not set, and has no default
value. Use a -var or -var-file command line argument to provide a value for
this variable.

Use the declared name with straight ASCII quotes:

bash
terraform plan -no-color -input=false -var='api_token=secret'
output
Plan: 1 to add, 0 to change, 0 to destroy.

  # terraform_data.label will be created
  + resource "terraform_data" "label" {
      + input = (sensitive value)
    }

Curly quotes from copied forum text produce the same undeclared-name error with a nearly invisible character in the reported name:

bash
terraform plan -no-color -input=false -var="$(printf '%b' '\342\200\234api_token=secret\342\200\235')"
output
Error: Value for undeclared variable

A variable named "“api_token" was assigned on the command line, but the root
module does not declare a variable of that name.

Re-type the flag manually with straight quotes, or use -var-file with a plain-text file you control. The verify/ directory plans successfully with:

bash
terraform plan -no-color -input=false -var-file=terraform.tfvars

Root versus child module variables

Child-module variables and root-module variables live in separate scopes. Passing a value requires a module argument; referencing var.app_name at the root requires a root variable block.

bash
mkdir -p ~/terraform-labs/terraform-undeclared-variable-error/errors/module-scope/modules/app
cd ~/terraform-labs/terraform-undeclared-variable-error/errors/module-scope

Child module expects app_name:

bash
cat > modules/app/main.tf <<'EOF'
variable "app_name" {
  type = string
}

resource "terraform_data" "app" {
  input = var.app_name
}
EOF

Root calls the module without the required argument:

bash
cat > main.tf <<'EOF'
terraform {
  required_version = ">= 1.12.0"
}

module "app" {
  source = "./modules/app"
}
EOF

Initialize before validating module calls:

bash
terraform init -input=false

With the child module on disk, validate reports the missing module argument:

bash
terraform validate -no-color
output
Error: Missing required argument

  on main.tf line 5, in module "app":
   5: module "app" {

The argument "app_name" is required, but no definition was found.

Pass the value at the call site in fixes/module-scope/:

hcl
module "app" {
  source   = "./modules/app"
  app_name = "demo"
}

A different mistake looks like Reference to undeclared input variable — root passes app_name = var.app_name but never declares variable "app_name" at the root. See errors/module-scope-alt-root-var/ in the lab tree for that variant. Child modules cannot read root variables unless you pass them in as arguments.


Diagnose variable names

When the error names a variable you thought you declared, check these in order:

  • Spelling — api_token versus api-token versus apitoken
  • Case — Environment and environment are different names
  • Hyphen versus underscore — CLI flags and HCL names must match the variable block exactly
  • Module scope — var.name inside a child module refers to that module's variables.tf, not the root
  • Assignment source — confirm the value comes from the file or flag you expect (terraform.tfvars, *.auto.tfvars, -var-file, -var)
  • Root declaration — module arguments that reference var.x still need variable "x" in the root module

terraform console can confirm a variable is in scope after you fix declarations — see terraform console for quick expression checks.


Verify the fix

The verify/ directory combines declared variables with a tfvars file:

bash
cd ~/terraform-labs/terraform-undeclared-variable-error/verify

Confirm configuration is valid:

bash
terraform validate -no-color
output
Success! The configuration is valid.

Plan with the tfvars file:

bash
terraform plan -no-color -input=false -var-file=terraform.tfvars
output
Plan: 1 to add, 0 to change, 0 to destroy.

  # terraform_data.label will be created
  + resource "terraform_data" "label" {
      + input = "demo-prod"
    }

Destroy lab resources when finished:

bash
terraform destroy -auto-approve -input=false 2>/dev/null || true

Diagnostic checklist

Symptom Likely cause Fix
Reference to undeclared input variable var.x in HCL, no variable block Add variable "x" in the same module
Value for undeclared variable warning Extra key in terraform.tfvars, *.auto.tfvars, or explicit -var-file Declare the variable or remove/fix the key
Value for undeclared variable error Wrong variable name passed with -var Match the declared variable name exactly
No value for required variable Name correct but no assignment Add -var, tfvars, or a default
Missing required argument on module Child input not passed from root Add app_name = ... to the module block
Undeclared var.x in module argument Root variable never declared Add root variable "x" or pass a literal

References


Summary

Terraform splits undeclared variable failures into two families. Reference to undeclared input variable means HCL mentions var.name without a variable block in that module — add the declaration or fix the reference. Value for undeclared variable means an assignment arrived from tfvars or the CLI for a name the module never declared — align the key with a real variable block or stop passing the extra value.

Extra terraform.tfvars keys warn when plan loads the assignment file, while wrong -var names fail at plan with an error and a paired No value for required variable message. Watch for hyphen versus underscore and curly quotes copied from documentation.

Module calls add a third pattern: Missing required argument when a child-module input is not passed from the root. Root and child variables are separate scopes — pass values through module arguments and declare root variables when module blocks reference var.x.

After fixes, terraform validate should be clean (or only show warnings you intend to address), and terraform plan with your tfvars or -var flags should bind every required input. For broader variable assignment patterns, continue with Terraform variables.


Frequently Asked Questions

1. What is the difference between Reference to undeclared input variable and Value for undeclared variable?

Reference to undeclared input variable means HCL uses var.name but no variable block exists in that module scope. Value for undeclared variable means a tfvars file or -var flag supplied a name the module never declared — the configuration syntax is fine but the assignment has nowhere to go.

2. Can terraform.tfvars create a variable automatically?

No. A key in terraform.tfvars or a -var-file only assigns a value to a variable that is already declared with a variable block in that module. Add the variable block or remove the extra assignment.

3. Why does terraform validate pass but plan fails on variables?

validate checks HCL structure and references inside configuration files. It does not evaluate every CLI assignment. A wrong -var name or a missing required value often appears only when plan tries to bind all input variables.

4. How do I fix undeclared variables in a child module?

Declare the variable inside the child module variables.tf, then pass a value from the root module block argument. Root-level variables and child-level variables are separate scopes — var.app_name at the root does not exist inside the module unless you declare it there too.

5. Can smart quotes break Terraform -var?

Yes. Copying a -var argument from a forum or document can insert curly quotation marks. Terraform then treats the variable name as including the quote character and reports Value for undeclared variable for a name you think you spelled correctly.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)