Terraform Error Guide: 'No value for required variable' (input variable is not set)
Fix Terraform's 'No value for required variable' error: pass values via tfvars, -var, or TF_VAR_ env, add sensible defaults, and wire variables correctly in CI.
- #terraform
- #troubleshooting
- #errors
- #variables
Exact Error Message
Error: No value for required variable
on variables.tf line 3:
3: variable "region" {
The root module input variable "region" is not set, and has no default value.
Use a -var or -var-file command line argument to provide a value for this
variable.
In automation, where interactive prompts are disabled, the same root cause surfaces with -input=false:
Error: No value for required variable
on variables.tf line 9:
9: variable "db_password" {
The root module input variable "db_password" is not set, and has no default
value. Use a -var or -var-file command line argument to provide a value for
this variable, or set the input variable's "default" attribute to provide a
default value.
What the Error Means
A variable block with no default is a required input. Terraform must obtain a value for it from somewhere before it can plan. When you run interactively, Terraform prompts you. When no value is supplied and prompting is disabled (CI, -input=false, or a non-TTY), the run fails with No value for required variable.
The fix is always to deliver the value through one of Terraform’s input channels, or to give the variable a default so it is no longer required. Which channel to use depends on whether the value is a secret, environment-specific, or a safe constant.
Common Causes
- Missing
-varor-var-file— you expected to pass it on the command line and forgot. - Missing
TF_VAR_environment variable — the value was meant to come fromTF_VAR_regionbut the variable is unset in the shell or CI job. - Required variable in non-interactive context — CI runs with
-input=false, so Terraform cannot prompt. - Typo in the tfvars filename —
terraform.tfvarsis auto-loaded, butprod.tfvarsis not unless you pass-var-file, and*.auto.tfvarsmust end exactly in.auto.tfvars. - Variable declared in a child module but not passed — the module declares it as required, and the calling
moduleblock omits it. - Wrong workspace/directory —
terraform.tfvarsexists, but you ran Terraform from a directory where it is not loaded.
How to Reproduce the Error
Declare a required variable and run a non-interactive plan without supplying it:
# variables.tf
variable "region" {
type = string
description = "AWS region to deploy into"
}
terraform plan -input=false
Error: No value for required variable
on variables.tf line 2:
2: variable "region" {
The root module input variable "region" is not set, and has no default value.
Diagnostic Commands
List every required variable (those without a default) so you know exactly what must be supplied:
grep -B1 -A4 'variable ' *.tf | grep -L default
terraform console <<<'var.region'
Check what tfvars files exist and which are auto-loaded — only terraform.tfvars and *.auto.tfvars load automatically:
ls -1 *.tfvars *.auto.tfvars 2>/dev/null
Confirm whether the value is coming from the environment:
env | grep '^TF_VAR_'
Run a plan that reports the resolved value without applying:
terraform plan -var-file=prod.tfvars
Step-by-Step Resolution
1. Pass the value on the command line for one-off runs:
terraform plan -var="region=us-east-1"
2. Put environment-specific values in a tfvars file and load it explicitly:
# prod.tfvars
region = "us-east-1"
db_name = "orders"
terraform plan -var-file=prod.tfvars
3. Use auto-loaded names when you want zero flags. Terraform loads terraform.tfvars and any file ending in .auto.tfvars automatically:
mv prod.tfvars prod.auto.tfvars
terraform plan
4. Supply secrets through TF_VAR_ environment variables so they never sit in a file:
export TF_VAR_db_password="$(vault kv get -field=password secret/db)"
terraform plan
5. Wire CI explicitly. In a non-interactive pipeline, set the env vars or pass -var-file, and keep -input=false so a missing value fails loudly instead of hanging:
TF_VAR_region=us-east-1 \
TF_VAR_db_password="$DB_PASSWORD" \
terraform plan -input=false -var-file=ci.tfvars
6. Pass required inputs to child modules in the calling block:
module "network" {
source = "./modules/network"
region = var.region # the module declared this as required
cidr = "10.0.0.0/16"
}
7. Add a default for genuinely optional values so they stop being required:
variable "region" {
type = string
default = "us-east-1"
}
Prevention and Best Practices
- Give safe, environment-agnostic values a
default; reserve no-default (required) for things that must be chosen per environment or are secrets. - Standardise on
*.auto.tfvarsper environment so the right file loads without remembering-var-file. - Never default secrets in code — pass them through
TF_VAR_*from a secrets manager or CI secret store. - Keep
-input=falsein all automation so a missing value fails fast instead of blocking on a prompt that never gets answered. - Document required variables in each module’s README, and add
descriptionto everyvariableblock. - Precedence to remember (lowest to highest): environment
TF_VAR_*,terraform.tfvars,*.auto.tfvars(alphabetical), then-var-fileand-varon the command line. Later sources win.
Related Errors
Invalid value for input variable— the value was supplied but failed avalidationblock or type constraint.Variables not allowed— usingvar.in a context Terraform evaluates too early (like abackendblock).Reference to undeclared input variable— referencingvar.xwith no matchingvariableblock.No value for required variablein a module — same error but raised by a child module whose required input the caller omitted.
Frequently Asked Questions
Why does my terraform.tfvars not get picked up? It only auto-loads from the directory Terraform runs in, and the filename must be exactly terraform.tfvars or end in .auto.tfvars. A file named prod.tfvars requires an explicit -var-file=prod.tfvars.
How do I pass a secret without putting it in a file or shell history? Export it as TF_VAR_<name> from your secrets manager in the same command, for example TF_VAR_db_password="$(vault kv get -field=password ...)" terraform plan. Mark the variable sensitive = true so it is redacted from output.
My pipeline hangs instead of erroring. Why? Without -input=false, Terraform tries to prompt for the missing variable. In CI there is no TTY to answer, so the job appears to hang until it times out. Always pass -input=false in automation.
What is the precedence when a variable is set in several places? Command-line -var and -var-file win over *.auto.tfvars, which win over terraform.tfvars, which wins over TF_VAR_* environment variables. The last -var on the line takes final precedence.
Should I just add a default to every variable to avoid this error? No. A default makes the variable optional, which can mask the fact that an environment-specific or secret value was never supplied. Keep those required and supply them through tfvars or TF_VAR_*.
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.