Terraform Error Guide: 'Missing required argument' — Fix Omitted Resource Arguments
Fix Terraform's 'Missing required argument' error: read the block and line it cites, check the provider schema for required vs optional arguments, add nested blocks, and pass module inputs.
- #terraform
- #iac
- #troubleshooting
- #errors
Stuck on this Terraform error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
Terraform raises “Missing required argument” during config parsing when a resource, data source, provider, or module block leaves out an argument the schema marks as required. The message names the block and the missing argument directly:
╷
│ Error: Missing required argument
│
│ on main.tf line 8, in resource "aws_instance" "web":
│ 8: resource "aws_instance" "web" {
│
│ The argument "ami" is required, but no definition was found.
╵
This is a static, provider-schema-level check: Terraform knows from the provider that aws_instance requires an ami, so it refuses to plan without one. The same error appears for required nested blocks (for example a setting block that must appear at least once) and for module input variables that have no default and were not passed by the caller.
Symptoms
terraform validateorplanfails immediately, citing an exact block and line.- The message reads “The argument “X” is required, but no definition was found.”
- A resource copied from an example or an older provider version suddenly reports a missing argument after a provider upgrade.
- A module fails with a missing required argument for one of its input variables.
Common Root Causes
- A genuinely omitted required argument — the resource simply lacks
ami,name,instance_type, etc. - A required nested block missing — some resources require at least one occurrence of a sub-block (e.g. an
ingress/egressorsettingblock). - A provider upgrade that promoted an argument to required, or renamed/split an argument between major versions.
- A module input variable with no
defaultthat the calling block never sets. - A typo in the argument name, so the intended argument is present but under the wrong key and the required one reads as absent.
- Copy-paste from documentation for a different provider version than the one pinned in your config.
Diagnostic Workflow
Run validate to get the precise block, line, and argument name — this is the whole diagnosis for most cases:
terraform validate
Check the provider schema to see exactly which arguments are required for the resource in question. terraform providers schema dumps the machine-readable schema so you can confirm required vs optional without guessing:
terraform providers schema -json | \
jq '.provider_schemas[].resource_schemas["aws_instance"].block.attributes
| to_entries[] | select(.value.required == true) | .key'
Cross-check against the registry documentation for the pinned provider version, then confirm what you actually have pinned:
terraform version # core + provider versions in use
terraform providers # provider requirements across the config
For a module, inspect its variables.tf to see which inputs lack a default and are therefore required from the caller:
# modules/vpc/variables.tf
variable "cidr_block" { # required: no default
type = string
}
variable "enable_flow_logs" { # optional: has a default
type = bool
default = false
}
Example Root Cause Analysis
A configuration that had planned cleanly for months started failing after a routine provider bump with The argument "ami" is required on an aws_instance block — yet the block clearly set an image, so the error looked wrong at first glance.
terraform validate confirmed the missing argument was ami. Reading the block revealed the image was set under ami_id, not ami — a typo that had gone unnoticed because the previous provider version had tolerated an implicit default in a launch-template path the config no longer used. The schema dump made it unambiguous: ami was required == true, and ami_id was not a recognised argument at all, so it was silently ignored while the required ami read as absent.
The fix was to use the correct argument name:
resource "aws_instance" "web" {
ami = "ami-0123456789abcdef0"
instance_type = "t3.micro"
tags = {
Name = "web"
}
}
After correcting the key, terraform validate passed and the plan showed the instance unchanged. A quick review of the provider changelog confirmed no other arguments had been promoted to required in the upgrade.
Prevention Best Practices
- Pin provider versions with a
required_providersblock and read the changelog before bumping major versions, where required arguments most often change. - Use
terraform providers schema -json(or the registry docs for the exact version) as the source of truth for required vs optional arguments, not memory or old examples. - Give module input variables sensible
defaultvalues where a default is safe, so callers are not forced to set every argument. - Enable editor/LSP support (terraform-ls) so missing-argument and typo errors surface as you type.
- Run
terraform validatein CI on every change to catch schema violations before they reachplan. - Sanity-check HCL structure with the Terraform validators before committing.
Quick Command Reference
terraform validate # names the block, line, and argument
terraform version # confirm core + provider versions
terraform providers # provider requirements in the config
terraform providers schema -json | jq ... # list required attributes for a resource
# module inputs without a `default` are required from the caller
Conclusion
“Missing required argument” is a schema-level check that fires before any plan: the provider (or a module’s variables.tf) declares an argument required, and your block omits it — often through a typo, a missing nested block, or an argument promoted to required in a provider upgrade. terraform validate gives you the exact location, and terraform providers schema removes all ambiguity about what is required. Pin providers, read changelogs, and default module inputs where safe. For more IaC fixes, see the Terraform guides.
Fixed it? Get 500 Terraform & DevOps AI prompts — free
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.
Stuck on this? Start guided troubleshooting
Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.
Did this fix your issue?
Solved it a different way?
Share the fix that worked for you — reviewed, then published to help the next engineer.
That looks like it may contain a secret (key, token, password, or connection string). Please remove it — a note with a detected secret can’t be published.
Thanks — that helps. Published notes appear after a quick review.
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4Transport endpoint is not connected
- 5modprobe: FATAL: Module not found
- 6mount: wrong fs type, bad option, bad superblock
Get 500 Battle-Tested DevOps AI Prompts — Free
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.