Skip to content

In an unknown choice of 1 of 2 lists, if the lists are the same length, the list length should be known #33237

@Nuru

Description

@Nuru

Terraform Version

Terraform v1.4.6
on darwin_amd64
+ provider registry.terraform.io/hashicorp/null v3.2.1
+ provider registry.terraform.io/hashicorp/random v3.5.1

Terraform Configuration Files

Of course this is very pared down from useful code:

bug.tf
variable "bug" {
  type = bool
  description = "set to true to trigger the bug"
  default = true
}

resource "random_integer" "coin" {
  max   = 2
  min   = 1
}

locals {
  coin_flip = random_integer.coin.result > 1

  rules = [
    {
      list        = (var.bug ? local.coin_flip : true) ? [null] : [null]
      description = "example description"
    }
  ]

  # Use concat to flatten the list of lists into a single list
  # instead of flatten because flatten depends on values.
  expanded_rules = concat(concat([[]], [for n, rule in local.rules : [for i, v in rule.list : {
    key         = "exp.${n}.${i}" 
    description = rule.description
    item        = "known" // In useful code, this would be `v`
  }]])...)

  keyed_rules = { for rule in local.expanded_rules : rule.key => rule }
}

resource "null_resource" "count" {
  count = length(local.keyed_rules)
  triggers = {
    description = values(local.keyed_rules)[count.index].description
  }
}

resource "null_resource" "for_each" {
  for_each = local.keyed_rules
  triggers = {
    description = each.value.description
  }
}

Debug Output

n/a

Expected Behavior

Terraform should be able to plan

Actual Behavior

The dreaded count and for_each errors:

Click to see Error Message
│ Error: Invalid count argument
│ 
│   on bug.tf line 32, in resource "null_resource" "count":
│   32:   count = length(local.keyed_rules)
│ 
│ The "count" value depends on resource attributes that cannot be determined
│ until apply, so Terraform cannot predict how many instances will be created.
│ To work around this, use the -target argument to first apply only the
│ resources that the count depends on.
╵
╷
│ Error: Invalid for_each argument
│ 
│   on bug.tf line 39, in resource "null_resource" "for_each":
│   39:   for_each = local.keyed_rules
│     ├────────────────
│     │ local.keyed_rules will be known only after apply
│ 
│ The "for_each" map includes keys derived from resource attributes that cannot
│ be determined until apply, and so Terraform cannot determine the full set of
│ keys that will identify the instances of this resource.

The unknown value of local.rules[0].list should not make it a list of unknown length, because both options are the same length, but it does.

Steps to Reproduce

  1. terraform init
  2. terraform plan -var bug=false # succeeds
  3. terraform plan -var bug=true # fails

Additional Context

This is part of the ongoing saga of not being able to use count or for_each because of derived values not known at plan time.

References

Originally posted by @apparentlymart in #26755 (comment)

The known-ness of an attribute value is independent of the known-ness of the object value it's contained within.

At first I thought that the unknown value of local.rules[0].list was making the other attributes in the object unknown. However, replacing

      list        = (var.bug ? local.coin_flip : true) ? [null] : [null]

with

      list        = [(var.bug ? local.coin_flip : true) ? null : null]

allows the plan to succeed, which indicates the problem is with the length of the list.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions