How to fix Error: Missing resource instance key - Because resource has for_each set, its attributes must be accessed on specific instances in Terraform

TerraformINTERMEDIATEMEDIUMUpdated Dec 30, 2025ยท 119 views

The 'Missing resource instance key' error occurs when you try to access attributes of a resource that has for_each set without specifying which instance to access. Fix it by using specific instance keys like aws_instance.example[each.key].id or using a for expression in outputs.

Quick fix

Fixes Error: Missing resource instance key - Because resource has for_each set, its attributes must be accessed on specific instances

# WRONG - will cause error
resource "aws_security_group_rule" "example" {
  source_security_group_id = aws_security_group.web_app.id
}

# CORRECT - specify the instance key
resource "aws_security_group_rule" "example" {
  for_each = var.rules
  source_security_group_id = aws_security_group.web_app[each.key].id
}
  1. Use bracket notation to access specific instances
  2. Use a for expression to iterate in outputs
  3. Fix IAM policy resources using ARNs from for_each
  4. Use dynamic blocks for complex multi-resource references
terraform โ€” error
# WRONG - will cause error
resource "aws_security_group_rule" "example" {
source_security_group_id = aws_security_group.web_app.id
}
# CORRECT - specify the instance key
resource "aws_security_group_rule" "example" {
for_each = var.rules
source_security_group_id = aws_security_group.web_app[each.key].id
}
Error: Missing resource instance key - Because resource has for_each set, its attributes must be accessed on specific instances

What this error means

This error occurs when Terraform tries to reference a resource that uses the `for_each` meta-argument without specifying which instance to access. When a resource is created with `for_each`, it becomes a map of instances rather than a single resource. Each instance is identified by a unique key from the `for_each` collection. Terraform cannot infer which specific instance you want to reference when you try to access a resource attribute directly. For example, if you have `aws_instance.web_app` with `for_each = var.instance_config`, you cannot access `aws_instance.web_app.id` because Terraform doesn't know which instance's ID you want. You must specify the key: `aws_instance.web_app["instance-1"].id` or iterate over all instances. This validation prevents ambiguous resource references that could lead to unpredictable behavior or unintended resource destruction when your configuration changes.

Typical symptoms

  • Terraform validate or plan fails immediately with 'Missing resource instance key' error
  • Error message specifies: 'Because resource has for_each set, its attributes must be accessed on specific instances'
  • Occurs when referencing resource attributes in outputs, variables, or other resource arguments
  • IAM policy JSON resources fail when using resource ARNs from for_each'd resources
  • Error appears when trying to pass resource attributes to modules or other resources
  • Works fine with count but breaks when switching to for_each

Common causes

  1. Directly accessing resource attributes without specifying the for_each key (e.g., aws_instance.web[*] instead of aws_instance.web[each.key])
  2. Using single-resource syntax when the resource is created with for_each (missing the bracket notation)
  3. Mixing count and for_each patterns or using count.index with for_each resources
  4. Attempting to use resource attributes in contexts that don't support iteration (like inline IAM policy resources)
  5. Referencing resources that recently changed from count to for_each without updating all references
  6. Not iterating over for_each resources when building collections or composite resources

How to fix "Error: Missing resource instance key - Because resource has for_each set, its attributes must be accessed on specific instances"

1Use bracket notation to access specific instances

When accessing a resource created with for_each, always specify the key using bracket notation:

hcl
# WRONG - will cause error
resource "aws_security_group_rule" "example" {
  source_security_group_id = aws_security_group.web_app.id
}

# CORRECT - specify the instance key
resource "aws_security_group_rule" "example" {
  for_each = var.rules
  source_security_group_id = aws_security_group.web_app[each.key].id
}

The key each.key refers to the current key from the for_each iteration. You can also use specific string keys if accessing a different for_each resource:

hcl
value = aws_instance.web_app["production"].id
2Use a for expression to iterate in outputs

When building outputs that reference multiple for_each instances, use a for expression to iterate over all instances:

hcl
# WRONG
output "instance_ids" {
  value = aws_instance.web_app.id
}

# CORRECT - iterate using for expression
output "instance_ids" {
  value = { for k, v in aws_instance.web_app : k => v.id }
}

# Or as a list
output "instance_ids" {
  value = [for instance in aws_instance.web_app : instance.id]
}

This creates an output that contains the IDs of all instances, properly referencing each one individually.

3Fix IAM policy resources using ARNs from for_each

When building IAM policies that reference resources created with for_each, use a for expression:

hcl
# WRONG - causes error
resource "aws_iam_role_policy" "example" {
  policy = jsonencode({
    Statement = [{
      Action = "s3:GetObject"
      Resource = aws_s3_bucket.example.arn  # ERROR if bucket uses for_each
    }]
  })
}

# CORRECT - iterate over instances
resource "aws_iam_role_policy" "example" {
  for_each = var.bucket_configs
  policy = jsonencode({
    Statement = [{
      Action = "s3:GetObject"
      Resource = aws_s3_bucket.example[each.key].arn
    }]
  })
}

# Or use a dynamic block
resource "aws_iam_role_policy" "example" {
  policy = jsonencode({
    Statement = [{
      Action = "s3:GetObject"
      Resource = [for bucket in aws_s3_bucket.example : bucket.arn]
    }]
  })
}
4Use dynamic blocks for complex multi-resource references

For more complex scenarios, use Terraform's dynamic block to generate resource configuration based on for_each instances:

hcl
resource "aws_security_group" "main" {
  name = "main-sg"

  dynamic "ingress" {
    for_each = aws_network_interface.example
    content {
      from_port       = 443
      to_port         = 443
      protocol        = "tcp"
      security_groups = [ingress.value.security_groups]
    }
  }
}

The dynamic block iterates over the for_each collection, making each instance available as ingress.value.

5Verify references are updated when converting from count to for_each

If you're migrating from count to for_each, ensure all references are updated:

hcl
# OLD (with count)
resource "aws_instance" "web_app" {
  count = var.instance_count
  # ...
}

output "ids" {
  value = aws_instance.web_app[*].id  # Works with count
}

# NEW (with for_each)
resource "aws_instance" "web_app" {
  for_each = var.instance_map
  # ...
}

output "ids" {
  value = [for instance in aws_instance.web_app : instance.id]  # Must use for expression
}

The splat syntax ([*]) works with count, but for_each requires explicit for expressions.

Advanced notes

Difference between count and for_each:

With count, resources are indexed by position (0, 1, 2...) and stored as a list. With for_each, resources are indexed by a user-specified key and stored as a map. This means:

- count uses splat syntax: aws_instance.web[*].id
- for_each requires explicit iteration: [for instance in aws_instance.web : instance.id]

Changing resource counts or reordering items in a count list causes Terraform to recreate downstream resources. Using for_each with stable keys prevents this issue, making it the preferred approach for complex configurations.

When to use each.key vs each.value:

- each.key - The key from your for_each map (usually a string identifier)
- each.value - The complete value object from your for_each map (useful for passing entire configuration objects)

Most commonly, you'll use each.key to access sibling resources and each.value to access the current resource's configuration.

Frequently asked questions

What does "Error: Missing resource instance key - Because resource has for_each s" mean?
This error occurs when Terraform tries to reference a resource that uses the for_each meta-argument without specifying which instance to access. When a resource is created with for_each, it becomes a map of instances rather than a single resource. Each instance is identified by a unique key from the for_each collection.
How do I fix "Error: Missing resource instance key - Because resource has for_each s"?
The 'Missing resource instance key' error occurs when you try to access attributes of a resource that has for_each set without specifying which instance to access. Fix it by using specific instance keys like aws_instance.example[each.key].id or using a for expression in outputs.
What causes "Error: Missing resource instance key - Because resource has for_each s"?
Directly accessing resource attributes without specifying the for_each key (e.g., aws_instance.web[*] instead of aws_instance.web[each.key]) Using single-resource syntax when the resource is created with for_each (missing the bracket notation) Mixing count and for_each patterns or using count.index with for_each resources
Is the "Error: Missing resource instance key - Because resource has for_each s" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading