Introduction
Terraform requires for_each keys to be known during planning. The error appears when a map or set is built from IDs, ARNs, or expressions that only become available after apply. The stable fix is to keep the keys static and move dynamic values into the object payload.
Symptoms
terraform planfails withInvalid for_each argument- The error says Terraform cannot determine the full set of keys
- The expression depends on IDs from resources created in the same run
- Adding
depends_ondoes not help because the keys are still unknown
Common Causes
- A
for_eachmap uses resource IDs as its keys - A
toset(...)expression depends on apply-time values - Locals combine outputs that do not exist until apply
- The configuration confuses identity with runtime attributes
Step-by-Step Fix
- 1.**Inspect the expression in
terraform console** - 2.Separate the unstable values from the stable identifiers before changing the resource block.
terraform console
> local.targets
> keys(local.targets)- 1.Replace dynamic keys with fixed names
- 2.Use logical names such as
public-aandpublic-b, then store unknown IDs inside the values.
```hcl locals { subnet_targets = { public-a = { subnet_id = aws_subnet.public_a.id } public-b = { subnet_id = aws_subnet.public_b.id } } }
resource "aws_route_table_association" "this" { for_each = local.subnet_targets subnet_id = each.value.subnet_id route_table_id = aws_route_table.public.id } ```
- 1.**Avoid
toset(...)when instance identity matters** - 2.Sets force Terraform to derive identity from the values themselves. Use an explicit map instead.
```hcl resource "aws_security_group_rule" "ingress" { for_each = { app = 8080 admin = 8443 }
from_port = each.value to_port = each.value protocol = "tcp" type = "ingress" security_group_id = aws_security_group.app.id } ```
- 1.Run a fresh plan and confirm the instance addresses are stable
- 2.A good fix removes the graph error and produces deterministic addresses under
for_each.
terraform planPrevention
- Design
for_eachmaps around business identifiers, not provider-generated IDs - Prefer maps over sets when lifecycle stability matters
- Use
terraform consoleearly during local refactors - Document expected keys for reusable modules