Home / Tutorials / Terraform

Terraform · Infrastructure as code · Deploy blocked

Fix: Invalid for_each argument

Error Error: Invalid for_each argument ... the "for_each" value depends on resource attributes that cannot be determined until apply

By the Erzon engineering team · A step-by-step fix, not a forum thread

This error means Terraform tried to expand a for_each but could not, because the keys of the collection it was given depend on something that will not exist until apply time. A typical trigger is keying a map on an ID that another resource outputs, like a subnet ID or an ARN. Terraform needs the keys during planning to build stable resource addresses, so a key that is unknown at plan time is a hard stop.

Error: Invalid for_each argument

  on main.tf line 21, in resource "aws_route53_record" "app":
  21:   for_each = { for s in aws_instance.web : s.id => s }

The "for_each" value depends on resource attributes that cannot be
determined until apply, so Terraform cannot predict how many instances
will be created. To work around this, use the -target argument to first
apply only the resources that the for_each depends on.

What this error means

Terraform builds a resource address for every element of a for_each, using the key as the index, for example aws_route53_record.app["web-1"]. Those addresses have to be known when Terraform draws the plan, so it can show you and later track each instance. When the keys are derived from a computed attribute such as .id or .arn, Terraform cannot know them until the upstream resource is actually created, so it cannot produce a stable plan and it refuses. The map values are allowed to be unknown; only the keys must be known.

Common causes

  • Keying a map on .id, .arn, or another attribute output by a resource that has not been created yet.
  • Using for_each over the result of a data source that itself depends on a resource created in the same run.
  • Building the collection with a for expression that pulls the key from a computed field.
  • A module output that passes through a computed ID and is then used as a for_each key downstream.
  • Toggling resources with a count or flag that is itself unknown until apply.

How to fix it

Stabilize

  1. Read the error and find the exact for_each line it names. Look at where the keys come from. If any part of the key expression references a resource attribute rather than a variable, local, or literal, that is the problem.
terraform plan

Diagnose

  1. Confirm which value is unknown. The key expression is the culprit, not the whole map. In the example above, the keys are s.id, which is computed. The values s are fine.

  2. Decide on a stable key you control. Names, keys you set in your own variables, or literal strings are all known at plan time. IDs and ARNs are not.

Fix

Key the map on a static value you define, and move the computed attribute into the value where unknown data is allowed. For the example, key on an instance name you set rather than the generated ID:

resource "aws_instance" "web" {
  for_each = toset(["api", "worker", "cron"])
  ami           = var.ami_id
  instance_type = "t3.micro"
  tags = { Name = each.key }
}

resource "aws_route53_record" "app" {
  for_each = aws_instance.web
  zone_id  = var.zone_id
  name     = "${each.key}.example.com"
  type     = "A"
  ttl      = 300
  records  = [each.value.private_ip]
}

Here the keys come from names you control, so they are known at plan time, and the computed private_ip sits in the value where it is allowed to be unknown.

If you cannot restructure right now and just need to unblock a deploy, apply the upstream resource first so its attributes become known, then run a normal plan:

terraform apply -target=aws_instance.web
terraform plan

Treat -target as a one time escape hatch. If the code still keys on computed values, the next clean run will fail the same way.

How to prevent it

  • Key every for_each on values you define: variable names, local map keys, or literals, never computed IDs.
  • Put computed attributes in the map values, not the keys, since values may be unknown at plan time.
  • Avoid chaining a for_each off a data source that depends on resources created in the same apply.
  • When passing collections between modules, pass stable keys through, not generated IDs.
  • Review new for_each blocks in code review for any reference to .id, .arn, or similar computed fields in the key position.

When to call a senior engineer

If restructuring the keys ripples through modules, forces resource addresses to change, and threatens to destroy and recreate live resources, the fix is no longer a one line change. Rekeying a for_each can move state addresses, and getting that wrong replaces infrastructure you meant to keep. Erzon engineers can rework the keying, plan the state moves with terraform state mv so nothing is destroyed, and keep your apply clean through the change.

Related errors we fix

Still down after this?

Want a senior engineer to just fix it?

Paste this exact error into the form. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.

Book a fix

← Back to all error fixes

Still down?

Get a senior engineer on it now

Leave your email and a line about what is happening. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.

Or email [email protected]. Same engineers, same one-hour clock.