mediumIntermediateSymptom-first#for-each#hcl#type#count

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

Likely source:configuration

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)'
READ

Check the variable type

Fix

terraform console -e 'toset(var.names)'
READ

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.

1
terraform plan 2>&1 | grep -A5 'for_each'
READ

Read the type error

2
terraform console -e 'type(var.<name>)'
READ

Check the variable type

3
terraform console -e 'toset(var.<name>)'
READ

Preview the toset conversion

4
terraform validate
READ

Confirm 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.

Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.