# Fix terraform "Error: Invalid index"

**TL;DR:** You indexed a list or looked up a map key that does not exist: an empty collection, or an index past the end. Print `length()` of the collection to confirm, then guard the access with a length check or `try()`, or fix whatever upstream data source returned the empty collection.

## The error

```text
Error: Invalid index

  on main.tf line 95, in locals:
  95:   subnet_id = tolist(data.aws_subnets.default.ids)[0]
      |----------------
      | data.aws_subnets.default.ids is empty list of string

The given key does not identify an element in this collection value: the collection has no elements.
```

## Steps

1. Confirm the collection is empty: add `output "debug_len" { value = length(data.aws_subnets.default.ids) }` and plan. Expected: it prints `0`.
2. Guard the access so an empty collection is legal:
   ```hcl
   subnet_id = length(data.aws_subnets.default.ids) > 0 ? tolist(data.aws_subnets.default.ids)[0] : null
   ```
   or `try(tolist(data.aws_subnets.default.ids)[0], null)`. Expected: plan proceeds with `null` instead of erroring.
3. Fix the upstream cause if the collection should not be empty. In the classic case the default VPC had no subnets (someone deleted them); recreate them with `aws ec2 create-default-subnet --availability-zone YOUR_AZ --region YOUR_REGION`. Expected: the data source returns subnets again.
4. Remove the debug output and re-plan. Expected: a clean plan.

## When this applies

- Any `Error: Invalid index` where the diagnostic shows an empty tuple/list or a key the map does not have.
- `[0]` on a data source result that can legitimately come back empty.

## When it does NOT apply

- `Invalid count argument`. That is about expansion with unknown values, not indexing a known-but-empty collection.
- `Invalid function argument`. That is a function receiving a wrong-typed value.

## Tool and version compatibility

- Terraform CLI 0.12+ through 1.x. `try()` exists since 0.13 and is the cleanest guard.

## Why it happens

Terraform indexing is strict: `list[0]` on an empty list is an error, not null. Data sources that filter aggressively (or infrastructure that drifted, like deleted default subnets) hand you an empty collection, and the index that worked last month blows up today.

## Edge cases and pitfalls

- During `destroy`, data sources can empty out mid-run as dependencies are torn down. Code that indexes `[0]` on a data source should be wrapped in `try()` if destroy must work.
- `element(list, index)` wraps around instead of erroring, which hides bugs. Prefer an explicit length check or `try()` so emptiness is visible.