Problem
When running a terraform plan or terraform apply, you may encounter an Error: Invalid index message indicating an attempt to access an element in an empty tuple.
Error: Invalid index
on main.tf line 16, in resource "aws_s3_bucket" "first-bucket":
16: bucket = "${module.test.names[0]}-bucket"
├────────────────
│ module.test.names is empty tuple
The given key does not identify an element in this collection value: the collection has no elements.Cause
This error occurs when your Terraform configuration attempts to access an index of a list or tuple that is empty. This often happens when a module's output is conditional, and in some cases, returns no elements.
Consider the following example configuration where a module creates a number of random_pet resources based on the howmany variable.
Here is the root module configuration.
# main.tf
variable "howmany" {
default = 0
}
module "test" {
source = "./modules/test"
howmany = var.howmany
}
resource "aws_s3_bucket" "first-bucket" {
bucket = "${module.test.names[0]}-bucket"
}Here is the child module configuration.
# modules/test/main.tf
variable "howmany" {}
resource "random_pet" "names" {
count = var.howmany
length = 5
}
output "names" {
value = random_pet.names[*].id
}When var.howmany is 0, the random_pet resource is not created, and the names output returns an empty tuple. The aws_s3_bucket resource then fails because it tries to access the first element ([0]) of this empty tuple.
Solutions
To resolve this issue, you must add a guard to handle cases where the tuple is empty. You can use either the try() function or a conditional expression.
Solution 1: Use the try() function
Use the try() function to attempt to access the index and provide a fallback value if the operation fails. This is often the cleanest and most readable solution.
Update your resource configuration to use try().
resource "aws_s3_bucket" "first-bucket" {
bucket = "${try(module.test.names[0], "my-default-bucket-name")}-bucket"
}Solution 2: Use a conditional expression
Use a conditional expression with the length() function to check if the tuple contains elements before attempting to access an index.
Update your resource configuration to use a conditional expression.
resource "aws_s3_bucket" "first-bucket" {
bucket = "${length(module.test.names) > 0 ? module.test.names[0] : "my-default-bucket-name"}-bucket"
}If the resource argument is optional, you can use null as the fallback value. If the argument is required, you must provide a valid default value, as shown in the examples.
Outcome
After applying one of the solutions to your configuration, re-run terraform plan. Terraform should now be able to correctly handle the empty tuple and either use the fallback value or skip the argument, allowing the plan to succeed without an Invalid index error.
Additional Information
- For more details on the
tryfunction, refer to the Terraformtry()function documentation. - To learn more about conditional logic in HCL, see the Conditional Expressions documentation.