This error occurs when for_each tries to iterate over resource attributes that are not known until apply time. Terraform requires all for_each keys to be known during the planning phase to predict resource creation.
Terraform uses two distinct phases: plan and apply. During the plan phase, Terraform must determine exactly how many resources will be created or modified. The for_each meta-argument requires all its keys to be known at this point. When your for_each expression depends on values that Terraform cannot determine until the actual apply phase (such as resource IDs, outputs, or computed attributes), Terraform cannot calculate the full set of instances and fails with this error.
Replace for_each keys that depend on resource attributes with static values defined in your configuration. For example:
# BAD - depends on resource ID (unknown at plan time)
for_each = toset(aws_instance.example[*].id)
# GOOD - uses static names from configuration
variable "instance_names" {
type = list(string)
default = ["web-1", "web-2", "web-3"]
}
for_each = toset(var.instance_names)This way, the for_each keys are known during planning.
If you need to create a fixed number of resources, use count instead:
resource "aws_instance" "example" {
count = 3
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}With count, you reference resources by index (aws_instance.example[0].id) rather than by key, avoiding the for_each planning issue.
Create the dependent resources first, then create the resources that depend on them:
1. First apply only the resources your for_each depends on:
terraform apply -target=aws_instance.example2. Then run the full apply:
terraform applyThis ensures the resource attributes are known before the for_each evaluation.
If you need to use dynamic values in your iteration, place them as map values, not keys:
# BAD - dynamic key
for_each = {
for name, config in var.configs :
aws_subnet.example[name].id => config # ID unknown at plan time
}
# GOOD - dynamic value, static key
for_each = var.configs
resource "aws_route_table_association" "example" {
for_each = each.value
subnet_id = aws_subnet.example[each.key].id # Referenced in resource, not for_each
route_table_id = aws_route_table.example.id
}When using modules, avoid passing values that depend on resource attributes as input variables for for_each:
# BAD
module "monitoring" {
for_each = toset(aws_instance.example[*].id)
...
}
# GOOD - pass instance names, derive dependencies in module
module "monitoring" {
for_each = toset(var.instance_names)
instance_id = aws_instance.example[each.value].id
}This keeps the for_each logic based on known values.
If using dynamic blocks, ensure the iterator is known at plan time:
# Instead of conditional iteration that fails in Terraform 1.6+
dynamic "rule" {
for_each = var.enabled ? var.rules : []
content {
...
}
}
# Use tomap() to make it work
dynamic "rule" {
for_each = var.enabled ? tomap({for r in var.rules : r.name => r}) : tomap({})
content {
...
}
}This is a fundamental Terraform limitation by design. Terraform separates planning and applying to show users what will change before making changes. The for_each meta-argument requires knowing all keys upfront to create the execution plan. This limitation applies to both regular for_each loops and dynamic blocks.
If you truly need to create resources based on apply-time values, consider using Terraform data sources, external data sources, or post-apply automation with other tools. In some cases, using local-exec provisioners with scripts can work around this, but this approach should be used cautiously as it reduces Terraform's visibility into state changes.
For AWS specifically, using -target as a workaround is generally acceptable for initial setup, but it should not be a permanent solution to your infrastructure code design.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform