How to Fix Terraform "Error: Invalid index" When Accessing List Elements

beginner๐Ÿ—๏ธ Terraform2026-04-07| Terraform CLI (v0.12.x to v1.x) on Linux, macOS, or Windows

Error Message

Error: Invalid index
#terraform#list#index#troubleshooting

The Problem: Accessing What Isn't There

Terraform throws an "Invalid index" error whenever you try to pull data from a list or map using a key that doesn't exist. It usually happens when you work with dynamic data. For instance, a module might return an empty list of subnet IDs if a feature is disabled, but your code still expects a value.

If you try to grab the first item using my_list[0] while my_list is empty, Terraform stops dead in its tracks. It won't guess what you want; it just fails.

The Error Message

Your console output will usually look like this:

โ”‚ Error: Invalid index
โ”‚ 
โ”‚   on main.tf line 24, in resource "aws_instance" "web":
โ”‚   24:   subnet_id = var.subnet_ids[0]
โ”‚     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
โ”‚     โ”‚ var.subnet_ids is empty list of string
โ”‚ 
โ”‚ The given key does not identify an element in this collection value.

Debug Process: Peek Inside the State

Before you change any code, verify exactly what Terraform sees. The terraform console command is really handy for this. It lets you test expressions against your actual infrastructure state without running a full plan.

  • Fire up terraform console in your terminal.
  • Enter the variable or attribute name (e.g., var.subnet_ids).
  • If the output is [] or {}, you've confirmed the collection is empty. Any direct index access will fail until that list is populated.

Solution 1: Use the try() Function

The try() function is often the cleanest fix. It tests a series of expressions and returns the first one that doesn't cause an error. Use it to provide a sensible fallback when a list might be empty.

# Instead of risky direct access:
# subnet_id = var.subnet_ids[0]

# Use a fallback value:
subnet_id = try(var.subnet_ids[0], "subnet-12345678")

# Or, allow it to be null if the resource supports it:
subnet_id = try(var.subnet_ids[0], null)

With try(), Terraform won't crash if var.subnet_ids is empty. It simply assigns your fallback value and moves on.

Solution 2: Conditional Logic with length()

Need more control? You can use a ternary operator with the length() function. This is perfect when your fallback depends on other complex logic or external variables.

resource "aws_instance" "web" {
  # Only grab the first ID if the list actually has items
  subnet_id = length(var.subnet_ids) > 0 ? var.subnet_ids[0] : var.backup_subnet_id
}

Solution 3: The element() Function and Its Quirk

The element() function behaves differently than standard bracket notation. It uses a modulo operation to "wrap around" the list. For example, element(["a", "b"], 2) returns "a" because the index 2 wraps back to 0. However, it still fails if the list is empty. Only use this if you are sure the list has at least one item.

# This will STILL error if var.subnet_ids is empty!
subnet_id = element(var.subnet_ids, 0)

Verification Steps

Once you've updated your HCL code, follow these steps to ensure everything is working correctly:

  • Run terraform plan. The "Invalid index" error should be gone.
  • Inspect the plan output. Check if the attribute is receiving the correct fallback value or showing as null.
  • Verify your input sources. If a list is unexpectedly empty, check the upstream module outputs or the .tfvars files that should be populating it.

Lessons Learned

Building resilient Terraform modules requires you to expect the unexpected. Relying on hard-coded indices like [0] is a risky move because it assumes your cloud provider or upstream modules will always return exactly what you expect. By wrapping data access in a try() block or a length check, you prevent deployment failures and make your code much easier to maintain across different environments.

Related Error Notes