OpenTofu Error Guide: 'Invalid for_each argument' — Fix Unknown Keys at Plan Time
Fix OpenTofu 'Invalid for_each argument' by giving for_each statically-known keys, staging applies with -target, or restructuring computed dependencies.
- #iac
- #infrastructure-as-code
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
OpenTofu must know the full set of instance keys a for_each will create at plan time, because those keys become part of each resource’s address in state. When the keys depend on a value that is only known after another resource is applied, the plan cannot be built and OpenTofu errors:
Error: Invalid for_each argument
on main.tf line 22, in resource "aws_route53_record" "this":
22: for_each = { for r in aws_instance.web : r.private_ip => r }
The "for_each" map includes keys derived from resource attributes that cannot be
determined until apply, and so OpenTofu cannot determine the full set of keys
that will identify the instances of this resource.
Symptoms
tofu planfails withInvalid for_each argumentand a note that keys “cannot be determined until apply.”- The
for_eachexpression references attributes of another resource (IDs, IPs, ARNs) computed on apply. - The config planned fine before you switched the source to a resource-derived collection.
- A related message:
The given "for_each" argument value is unsuitable: the given "for_each" argument value is nullor contains unknown values.
Common Root Causes
- Keys derived from computed attributes —
for_eachover a map whose keys come fromaws_instance.*.private_ip, an ARN, or any post-apply value. for_eachover a resource that does not exist yet in the same apply.- Data source not yet readable at plan — a
datablock that depends on a resource created in the same run. - Unknown-length collections —
for_eachon the result of a function fed unknown values. - Conflating values and keys — it is fine for map values to be unknown, but keys must be known at plan.
Diagnostic Workflow
Reproduce and read which expression feeds for_each:
tofu plan 2>&1 | sed -n '1,25p'
Inspect the resource and what its for_each depends on:
grep -nA4 "for_each" main.tf
Check whether the source attribute is computed (known only after apply) by looking at the dependency:
tofu graph | grep -i "aws_instance.web"
Confirm the keys are the problem, not the values — try keying on a static input instead:
# static keys from a variable = known at plan; values may stay computed
grep -nA4 "variable \"names\"" variables.tf
Example Root Cause Analysis
An engineer wanted a DNS record per web instance:
resource "aws_route53_record" "this" {
for_each = { for r in aws_instance.web : r.private_ip => r }
# ...
}
tofu plan failed with Invalid for_each argument because r.private_ip is assigned by AWS at apply time, so the keys of the map were unknown at plan — OpenTofu could not determine how many records to create or their addresses.
The fix was to key the map on something known at plan time. The instances themselves were created with a static for_each over a variable of names, so each instance already had a known key. Re-expressing the records to key on that same static name (for k, inst in aws_instance.web : k => inst) made the record keys plan-known, while the value (inst.private_ip) stayed computed and resolved at apply — which is allowed. Where truly no static key existed, the alternative was a staged apply: tofu apply -target=aws_instance.web first, then a normal apply so the IPs were known before the records planned.
Prevention Best Practices
- Key
for_eachon values known at plan time (input variables, static locals), never on computed resource attributes. - It is fine for map values to be unknown at plan — only the keys must be known; restructure so keys come from static inputs.
- When keys genuinely depend on apply-time data, split into stages with
-target, or move the dependency into a separate apply. - Prefer deriving both instances and their dependents from the same static source so their keys line up.
- Avoid
countwith unstable ordering as a workaround; it causes churn on list changes.
Quick Command Reference
tofu plan # reproduce the error
grep -nA4 "for_each" *.tf # find the offending expression
tofu graph | grep <resource> # see the dependency edge
tofu apply -target=aws_instance.web # staged apply to resolve keys
tofu plan # re-plan with keys now known
Conclusion
Invalid for_each argument means the keys of your for_each are computed and thus unknown at plan time, so OpenTofu cannot address the instances it would create. The durable fix is to key on statically-known inputs (variables or locals) and let only the values stay computed. When a dependency truly forces apply-time keys, stage the apply with -target so the keys are known before the dependent resource plans.
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.