The index is greater than or equal to the length of the collection

Hey all, I’m using a configuration that works well in aws commercial but when I bring it to the government side, I get some odd behavior. Currently erroring on:

The given key does not identify an element in this collection value: the given index is greater than or equal to the length of the collection.

These are the details:

% tf version                                                                                                                                                                    
Terraform v1.5.7
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v5.22.0

This is a fairly common case; nothing special. I want to:

  1. discover AZs in a given region
  2. use the first n (var.minDistSize=3) AZs found; don’t care which
  3. distribute n number of subnets over those AZs
data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_subnet" "vpc_network" {
  vpc_id                          = aws_vpc.vpc_network.id
  count                           = var.minDistSize    # set to '3'
  map_public_ip_on_launch         = true
  assign_ipv6_address_on_creation = true

  # Get AZs from Region
  availability_zone = data.aws_availability_zones.available.names[count.index]

  cidr_block      = cidrsubnet(var.host_cidr, 2, count.index)
...
  }
}

The plan shows that the names are being enumerated correctly:

Plan: 33 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + az-names = [
      + "us-gov-east-1a",
      + "us-gov-east-1b",
      + "us-gov-east-1c",
    ]
╷
│ Error: Invalid index
│ 
│   on mods/infras/networking.tf line 31, in resource "aws_subnet" "vpc_network":
│   31:   availability_zone = data.aws_availability_zones.available.names[count.index]
│     ├────────────────
│     │ count.index is 3
│     │ data.aws_availability_zones.available.names is list of string with 3 elements
│ 
│ The given key does not identify an element in this collection value: the given index is greater than or equal to the length of the collection.

I’m requesting the first 3 AZs and, it appears, getting them; they’re enumerated in the output so I’m ignoring the 3 elements bit.

Also, TF is confirming that “index is greater than or equal to”; cool(I guess?). It’s technically correct so I’m a bit confused.

It’s also worth noting that the AZs seem to be populating the subnets as expected:

  # module.clusters.aws_subnet.vpc_network[0] will be created
  + resource "aws_subnet" "vpc_network" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = true
      + availability_zone                              = "us-gov-east-1a"
...
    }

  # module.clusters.aws_subnet.vpc_network[1] will be created
  + resource "aws_subnet" "vpc_network" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = true
      + availability_zone                              = "us-gov-east-1b"
...
    }

  # module.clusters.aws_subnet.vpc_network[2] will be created
  + resource "aws_subnet" "vpc_network" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = true
      + availability_zone                              = "us-gov-east-1c"
...
    }

I’ve described AZs in both Commercial and Gov, they seem to be structured the same:

% aws ec2 describe-availability-zones --region us-east-1 --output text
AVAILABILITYZONES       us-east-1       us-east-1       opt-in-not-required     us-east-1       available       use1-az4        us-east-1a      availability-zone
AVAILABILITYZONES       us-east-1       us-east-1       opt-in-not-required     us-east-1       available       use1-az6        us-east-1b      availability-zone
AVAILABILITYZONES       us-east-1       us-east-1       opt-in-not-required     us-east-1       available       use1-az1        us-east-1c      availability-zone
AVAILABILITYZONES       us-east-1       us-east-1       opt-in-not-required     us-east-1       available       use1-az2        us-east-1d      availability-zone
AVAILABILITYZONES       us-east-1       us-east-1       opt-in-not-required     us-east-1       available       use1-az3        us-east-1e      availability-zone
AVAILABILITYZONES       us-east-1       us-east-1       opt-in-not-required     us-east-1       available       use1-az5        us-east-1f      availability-zone

% aws ec2 describe-availability-zones --region us-gov-east-1 --output text
AVAILABILITYZONES       us-gov-east-1   us-gov-east-1   opt-in-not-required     us-gov-east-1   available       usge1-az1       us-gov-east-1a  availability-zone
AVAILABILITYZONES       us-gov-east-1   us-gov-east-1   opt-in-not-required     us-gov-east-1   available       usge1-az2       us-gov-east-1b  availability-zone
AVAILABILITYZONES       us-gov-east-1   us-gov-east-1   opt-in-not-required     us-gov-east-1   available       usge1-az3       us-gov-east-1c  availability-zone

So, it seems like the error is about the “key”?

Questions:
What does the error mean in this case: “The given key does not identify an element in this collection value”?
The output shows the AZ names; that’s what was requested/retuned. Which key?

Again, this bit of Terraform totally works in Commercial but it flakes in Gov. Is this a provider issue or something about Gov cloud I haven’t discovered yet?

Okay, this was a simple case of too much coffee and not enough testing. I set a variable in 2 places and TF became confused

% echo $TF_VAR_minDistSize | terraform console                                                                                                                                  
Acquiring state lock. This may take a few moments...
3

toddthomas@vsmbp infras-gov-eks % echo var.minDistSize | terraform console
4

Ugh, the grind of endless experiments :roll_eyes:

Resolved!