Invalid for_each — must be a map, set, or object
The given "for_each" argument value is unsuitable: must be a map, or set of strings
Focused incident mode — strips away everything but this runbook.
Symptoms
- The given "for_each" argument value is unsuitable: must be a map, or set of strings
- for_each on a list type produces a type error
- terraform apply fails with for_each type mismatch
Evidence to grab
Collect these artifacts before you change anything — they prove (or rule out) each cause.
for_each type error
terraform plan 2>&1 | grep -A5 'for_each'Variable type declaration
grep -B2 -A5 'variable' variables.tf
Diagnostic flow
Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.
Guided decision tree is ready.
Steps with commands, expected output, and pass/fail branches.
Ranked root causes
Evidence checklist
- for_each = var.names where var.names is list(string)
- Error: must be a map, or set of strings
Confirm before fixing
terraform console -e 'type(var.names)'Check the variable type
Fix
terraform console -e 'toset(var.names)'Preview the fix — toset() converts list to set
Resolution runbook
Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.
terraform plan 2>&1 | grep -A5 'for_each'Read the type error
terraform console -e 'type(var.<name>)'Check the variable type
terraform console -e 'toset(var.<name>)'Preview the toset conversion
terraform validateConfirm the fix compiles
Prevention
- Declare variables as set(string) or map(string) when used with for_each.
- Use toset() when converting lists to sets for for_each.
- Use terraform validate in CI to catch type errors before plan.
- Add variable type constraints with validation blocks.
Related runbooks
Same stack, same failure family — worth a skim.
An argument named "instance_typo" is not expected here
Error: Cycle: resource A -> resource B -> resource A
Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.