The Terraform element() function fails when applied to empty lists or tuples. This error commonly occurs when conditional logic causes data sources or resource counts to return zero results.
In Terraform, the element(list, index) function retrieves a single element from a list using zero-based indexing. The error occurs because element() cannot safely access indices from an empty list—there are no elements to retrieve. This typically happens when: 1. A data source query returns no results 2. A count conditional evaluates to 0, creating no resources 3. A variable contains an empty list by default Terraform evaluates all expressions during planning, so even if you guard with a conditional, both branches are still evaluated, causing the error.
The try() function evaluates an expression and returns a fallback value if it errors. This is the recommended approach for Terraform 0.13+:
locals {
first_subnet = try(element(aws_subnet.public[*].id, 0), null)
}If element() fails (empty tuple), it returns null instead of erroring.
Explicitly check if the list has elements before accessing them:
subnet_id = length(local.subnets) > 0 ? element(local.subnets, 0) : nullNote: This may still error in some cases because Terraform evaluates both branches. Combine with try() for safety:
subnet_id = length(local.subnets) > 0 ? try(element(local.subnets, 0), null) : nullIf your list should only have one element, use the one() function instead:
locals {
single_item = one(var.my_list)
}one() returns the single element if the list has exactly one item, or errors if empty or has multiple items.
Replace empty lists with defaults using coalescelist():
locals {
effective_list = coalescelist(var.my_list, ["default_value"])
first = element(local.effective_list, 0)
}This ensures element() always receives a non-empty list.
Check that your data source query filters are correct and actually match resources:
data "aws_subnets" "available" {
filter {
name = "vpc-id"
values = [aws_vpc.main.id] # Ensure VPC exists first
}
}
# Only reference if subnets were found
resource "aws_nat_gateway" "example" {
count = length(data.aws_subnets.available.ids) > 0 ? 1 : 0
subnet_id = try(element(data.aws_subnets.available.ids, 0), null)
allocation_id = aws_eip.nat[0].id
}Instead of using count with element(), consider for_each which naturally handles empty collections:
locals {
subnets = {
for subnet in var.subnets : subnet.name => subnet
}
}
resource "aws_route" "example" {
for_each = local.subnets
route_table_id = aws_route_table.main.id
# Direct iteration avoids element() entirely
}In modules like terraform-aws-vpc, this error often occurs when availability zones don't match the number of subnet configurations (e.g., 6 AZs but only 3 subnet sets). The workaround is to either add dummy elements to lists or redesign iteration to use resource counts instead of AZ iteration.
Teraform's early evaluation of all branches in conditional expressions means ternary operators alone won't prevent this error—always combine length checks with try() for reliability.
For null providers and dynamic resources, prefer using dynamic blocks or for_each over conditional element() calls.
Error: Error rendering template: template not found
How to fix "template not found" error in Terraform
Error: Error generating private key
How to fix 'Error generating private key' in Terraform
Error creating Kubernetes Service: field is immutable
How to fix "field is immutable" errors in Terraform
Error: Error creating local file: open: permission denied
How to fix "Error creating local file: permission denied" in Terraform
Error: line endings have changed from CRLF to LF
Line endings have changed from CRLF to LF in Terraform