How to fix Error: Invalid each attribute - The each object does not have an attribute named id in Terraform

TerraformINTERMEDIATEMEDIUMUpdated Dec 30, 2025· 98 views

This Terraform error occurs when you reference an attribute on the 'each' object that doesn't exist. The 'each' object only provides 'key' and 'value' attributes. Fix it by using the correct attribute or checking your for_each input structure.

Quick fix

Fixes Error: Invalid each attribute - The each object does not have an attribute named id

resource "aws_instance" "example" {
  for_each = var.instances

  ami           = each.id          # ERROR: 'each' has no 'id' attribute
  instance_type = each.name        # ERROR: 'each' has no 'name' attribute
}
  1. Understand the each object structure
  2. Verify your for_each data structure
  3. Use the correct each reference based on data type
  4. Fix common for_each mistakes
terraform — error
resource "aws_instance" "example" {
for_each = var.instances
ami = each.id # ERROR: 'each' has no 'id' attribute
instance_type = each.name # ERROR: 'each' has no 'name' attribute
}
Error: Invalid each attribute - The each object does not have an attribute named id

What this error means

The "Invalid each attribute" error in Terraform indicates that you're trying to access an attribute on the "each" object that doesn't exist. When using "for_each" to iterate over resources or modules, Terraform provides exactly two attributes on the "each" object: "key" (the current map key) and "value" (the current map value). This error commonly occurs when developers try to access attributes that don't exist on the "each" object itself, such as "id", "name", or other properties. The error can also happen when the data structure passed to "for_each" doesn't match what the code expects, or when trying to access nested properties using dot notation without understanding the data structure. Unlike "count.index" which provides a numeric index, or "count.primary" which provides a boolean, the "each" object has a fixed, simple interface with only "key" and "value" available for all iterations.

Typical symptoms

  • Plan or apply fails with 'The each object does not have an attribute named [attribute]'
  • Error references a specific attribute like 'id', 'name', or other property
  • Error occurs during 'terraform plan' or 'terraform apply'
  • Code that was working previously suddenly fails after changing data structures
  • Mixing for_each with count-style attribute references (like each.id)
  • Trying to access nested properties directly on the each object

Common causes

  1. Attempting to access an attribute that doesn't exist on the each object (only 'key' and 'value' are available)
  2. Using each.id instead of each.key or each.value when iterating
  3. Forgetting that each.value is the entire object when using complex data structures
  4. Misunderstanding the structure of the data passed to for_each (expecting a list when it's a map, or vice versa)
  5. Trying to access nested attributes without proper object property access syntax
  6. Copy-pasting code from count-based iteration and not updating each references correctly

How to fix "Error: Invalid each attribute - The each object does not have an attribute named id"

1Understand the each object structure

The "each" object in Terraform only provides two attributes, regardless of the data being iterated:

Available attributes:
- each.key: The key from the map (string)
- each.value: The value from the map (can be a string, number, object, list, etc.)

Incorrect - trying to access non-existent attributes:

hcl
resource "aws_instance" "example" {
  for_each = var.instances

  ami           = each.id          # ERROR: 'each' has no 'id' attribute
  instance_type = each.name        # ERROR: 'each' has no 'name' attribute
}

Correct - using only 'key' and 'value':

hcl
resource "aws_instance" "example" {
  for_each = var.instances

  ami           = each.value.ami
  instance_type = each.value.instance_type

  tags = {
    Name = each.key  # Use the key for naming
  }
}

Remember: no matter what data structure you pass to "for_each", you always access it through "each.key" and "each.value".

2Verify your for_each data structure

Make sure you understand what data structure you're iterating over:

When iterating a map of objects:

hcl
variable "instances" {
  type = map(object({
    ami           = string
    instance_type = string
  }))
  default = {
    web = {
      ami           = "ami-12345"
      instance_type = "t2.micro"
    }
    db = {
      ami           = "ami-67890"
      instance_type = "t2.small"
    }
  }
}

resource "aws_instance" "example" {
  for_each = var.instances

  ami           = each.value.ami              # Access nested properties through 'value'
  instance_type = each.value.instance_type
  tags = {
    Name = each.key                           # 'key' is "web" or "db"
  }
}

When iterating a set of strings:

hcl
variable "availability_zones" {
  type    = set(string)
  default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}

resource "aws_subnet" "example" {
  for_each = var.availability_zones

  availability_zone = each.value    # 'value' is the zone string directly
  vpc_id            = aws_vpc.main.id

  tags = {
    Name = "subnet-${each.key}"    # 'key' is auto-generated index for sets
  }
}

Print your variables during development to verify structure:

hcl
output "debug_instances" {
  value = var.instances
}
3Use the correct each reference based on data type

Different data types passed to "for_each" require different access patterns:

For map(object): Use each.key for the map key and each.value to access object properties:

hcl
for_each = {
  "web-1" = { size = "t2.micro", az = "us-east-1a" }
  "web-2" = { size = "t2.micro", az = "us-east-1b" }
}

instance_type = each.value.size    # Not each.instance_type or each.size
tags = { Name = each.key }         # 'web-1' or 'web-2'

For map(string): Use each.value as the string directly:

hcl
for_each = {
  "web" = "ami-12345"
  "db"  = "ami-67890"
}

ami = each.value    # Not each.ami or each.key

For list converted to map: Convert list to map first using tomap():

hcl
# Instead of for_each = var.my_list (which fails for non-sets/maps)
for_each = { for idx, item in var.my_list : idx => item }

# Access the item through each.value
resource_name = each.value.name    # Not each.name or each.id

Never use count-style attributes:

hcl
# WRONG - count attributes don't work with for_each
each.id          # ❌ Doesn't exist
each.index       # ❌ Doesn't exist (use count.index with count, not for_each)
each.count       # ❌ Doesn't exist

# CORRECT - only for_each attributes
each.key         # ✅ The map key
each.value       # ✅ The map value
4Fix common for_each mistakes

Here are fixes for the most common patterns that trigger this error:

Mistake 1: Using each.id when you mean each.key:

hcl
# ❌ Wrong
for_each = toset(["web", "db", "cache"])
resource "aws_security_group" "example" {
  name = each.id
}

# ✅ Correct
for_each = toset(["web", "db", "cache"])
resource "aws_security_group" "example" {
  name = each.value
}

Mistake 2: Accessing nested properties incorrectly:

hcl
# ❌ Wrong - trying to access nested property directly
for_each = var.instances
instance_type = each.instance_type

# ✅ Correct - use each.value then the property
for_each = var.instances
instance_type = each.value.instance_type

Mistake 3: Mixing up key and value usage:

hcl
# ❌ Wrong
for_each = { a = "value1", b = "value2" }
output_name = each.value    # When you meant the key

# ✅ Correct
for_each = { a = "value1", b = "value2" }
output_name = each.key      # If you want the key (a or b)
output_data = each.value    # If you want the value (value1 or value2)

Mistake 4: Using list instead of map/set:

hcl
# ❌ Wrong - lists are not supported directly by for_each
for_each = ["item1", "item2", "item3"]

# ✅ Correct - convert to set or map
for_each = toset(["item1", "item2", "item3"])
# OR
for_each = { for idx, item in ["item1", "item2", "item3"] : idx => item }
5Debug by printing the for_each data structure

When you're unsure about your data structure, add debug outputs to understand what you're iterating over:

hcl
variable "my_resources" {
  type = any  # Temporary - use 'any' to accept any structure
}

output "debug_for_each" {
  value = var.my_resources
}

output "debug_for_each_type" {
  value = "Type check: ${jsonencode(var.my_resources)}"
}

resource "aws_instance" "example" {
  for_each = var.my_resources

  # Debug output for each iteration
  tags = {
    DebugKey   = each.key
    DebugValue = jsonencode(each.value)
  }
}

Then run:

bash
terraform plan

Check the debug outputs to see exactly what structure you're working with. This helps you understand whether "each.value" is a string, number, object, or something else.

Use Terraform console to test expressions:

bash
terraform console
> var.my_resources
> keys(var.my_resources)
> values(var.my_resources)
6Use each with modules and data sources

The same principles apply when using "for_each" with modules and data sources:

With modules:

hcl
variable "subnet_config" {
  type = map(object({
    cidr_block = string
    az         = string
  }))
}

module "subnets" {
  for_each = var.subnet_config

  source = "./modules/subnet"

  name       = each.key              # Map key
  cidr_block = each.value.cidr_block # Nested property
  az         = each.value.az
}

# Access module outputs
output "subnet_ids" {
  value = { for k, v in module.subnets : k => v.subnet_id }
}

With data sources:

hcl
data "aws_ami" "example" {
  for_each = toset(["ubuntu", "amazon-linux", "centos"])

  filter {
    name   = "name"
    values = ["${each.value}-ami-*"]  # Use each.value directly
  }
}

output "ami_ids" {
  value = { for k, v in data.aws_ami.example : k => v.id }
}

Remember: even with modules and data sources, the "each" object still only has "key" and "value" attributes.

Advanced notes

Understanding for_each vs count:
- "for_each" creates resources with map-based keys and provides "each.key"/"each.value"
- "count" creates resources with numeric indices and provides "count.index"
- Do not mix attributes: use "each.*" with for_each and "count.*" with count

for_each vs splat expressions:
When you use "for_each" on a resource, you cannot use splat expressions like "aws_instance.example[*].id". Instead, convert to values:

hcl
# Wrong with for_each
output "ids" {
  value = aws_instance.example[*].id
}

# Correct with for_each
output "ids" {
  value = { for k, v in aws_instance.example : k => v.id }
}

Dynamic blocks and for_each:
When using "for_each" within a resource and also using dynamic blocks inside:

hcl
resource "aws_lb_listener_rule" "example" {
  for_each = var.rules

  dynamic "condition" {
    for_each = each.value.conditions
    content {
      path_pattern {
        values = [condition.value.path]
      }
    }
  }
}

Sensitive data in for_each:
Be aware that "for_each" values appear in state and plan outputs. For sensitive data:

hcl
resource "aws_instance" "example" {
  for_each = var.instances

  ami = each.value.ami

  # Mark sensitive data
  tags = {
    Password = sensitive(each.value.password)  # Won't show in output
  }
}

Changing for_each keys:
Adding or removing keys in "for_each" will destroy and recreate resources. Use stable identifiers in your map keys when the resource needs to persist.

Frequently asked questions

What does "Error: Invalid each attribute - The each object does not have an attri" mean?
The "Invalid each attribute" error in Terraform indicates that you're trying to access an attribute on the "each" object that doesn't exist. When using "for_each" to iterate over resources or modules, Terraform provides exactly two attributes on the "each" object: "key" (the current map key) and "value" (the current map value). This error commonly occurs when developers try to access attributes that don't exist on the "each" object itself, such as "id", "name", or other properties.
How do I fix "Error: Invalid each attribute - The each object does not have an attri"?
This Terraform error occurs when you reference an attribute on the 'each' object that doesn't exist. The 'each' object only provides 'key' and 'value' attributes. Fix it by using the correct attribute or checking your for_each input structure.
What causes "Error: Invalid each attribute - The each object does not have an attri"?
Attempting to access an attribute that doesn't exist on the each object (only 'key' and 'value' are available) Using each.id instead of each.key or each.value when iterating Forgetting that each.value is the entire object when using complex data structures
Is the "Error: Invalid each attribute - The each object does not have an attri" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading