This error occurs when Terraform tries to access a list or map element using an index that doesn't exist. Common causes include accessing empty lists, using count with mismatched list sizes, or using incorrect index calculations.
The 'Invalid index - out of range' error happens when your Terraform configuration attempts to access an element in a list, tuple, or map using an index number that exceeds the bounds of that collection. This is a validation error that Terraform catches during the planning phase. For example, trying to access element [2] in a list that only has 2 elements (indices 0 and 1) will trigger this error. This commonly occurs when using dynamic count or for_each iterations, data source queries that return unexpected numbers of results, or splat expressions combined with direct indexing.
Check that any list you're indexing actually has the number of elements you expect. Use Terraform console to inspect the actual data:
terraform console
> var.my_list
> length(var.my_list)If the list is empty or smaller than expected, this is your root cause.
Wrap direct index access with a length check to safely access elements only if they exist:
value = length(var.my_list) > 0 ? var.my_list[0] : nullThis ensures you only attempt to access indices that exist in the collection.
Use the try() function (available in Terraform 0.13+) to gracefully handle out-of-range access:
value = try(var.my_list[2], "default_value")If the index doesn't exist, try() returns the second argument (fallback value) instead of erroring.
The element() function provides safer list access and can wrap around if needed:
# Instead of:
value = var.my_list[count.index]
# Use:
value = element(var.my_list, count.index)This is particularly useful when working with count-based iteration.
If you're managing multiple resources, use for_each instead of count to avoid index-based problems:
resource "aws_instance" "example" {
for_each = var.instances # Use map keys instead of indices
ami = each.value.ami
instance_type = each.value.type
}for_each uses keys rather than numeric indices, preventing issues when adding/removing items.
When accessing data source results, always verify the query returned data:
data "aws_instances" "example" {
filter {
name = "tag:Name"
values = ["MyInstance"]
}
}
resource "aws_security_group_rule" "example" {
# Safe access - only if data source returned results
instance_id = length(data.aws_instances.example.ids) > 0 ? data.aws_instances.example.ids[0] : null
}This prevents errors when queries unexpectedly return no results.
When using splat expressions combined with direct indexing like resource.*.id[count.index], consider using the one() function (Terraform 1.0+) for single results or dropping the bracket entirely: resource.*.id returns all IDs directly. If you absolutely need bracket notation, use element(resource.*.id, count.index) instead. Be particularly careful when modifying count values mid-project - Terraform may destroy and recreate resources if you change from one index to another. Use state management commands like terraform state rm and terraform import if you encounter persistent state conflicts.
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