Terraform: Resource for_each not working with empty list

Created on 1 Aug 2019  ยท  4Comments  ยท  Source: hashicorp/terraform

Terraform Version

Terraform v0.12.6
+ provider.google v2.11.0
+ provider.null v2.1.2
+ provider.random v2.1.2

Terraform Configuration Files

variable "datalab_user_list" {
    type = list(string)
    default = []

}
resource "google_service_account" "datalab_service_account" {
    for_each = toset(var.datalab_user_list)
    account_id = "datalab-${split("@", each.key)[0]}"
    project = google_project.hipaa_project.project_id
}

Debug Output

Crash Output

Expected Behavior


Terraform plan and apply are successful and no resources are created

Actual Behavior

Error: Invalid for_each set argument

  on .terraform/modules/hipaa_worker_project1/datalab.tf line 23, in resource "google_service_account" "datalab_service_account":
  23:     for_each = toset(var.datalab_user_list)

The given "for_each" argument value is unsuitable: "for_each" supports maps
and sets of strings, but you have provided a set containing type dynamic.

Steps to Reproduce


Try to use an empty list with for_each on a resource.

Additional Context


As a workaround, this seems to work fine:

variable "datalab_user_list" {
    type = "map"
    default = {}

}
resource "google_service_account" "datalab_service_account" {
    for_each = var.datalab_user_list
    account_id = "datalab-${split("@", each.key)[0]}"
    project = google_project.hipaa_project.project_id
}

However, I don't really need a map and it makes what I pass in to the module a bit more confusing to read.

References

bug config v0.12

Most helpful comment

Ahh, thanks for reporting this!

Indeed, this is a quirk caused by the fact that in toset([]) there are no elements to hint the function as to what the set element type should be, and so "dynamic" here really means "unknown".

For now I think the most reliable workaround would be to manually convert to a map instead of a set, which shouldn't run into the same problem because map keys are _always_ strings:

  for_each = { for v in var.datalab_user_list : v => v }

A conversion like the above is essentially what Terraform itself does when handling a set of strings, but it checks the set element type first to produce that "Invalid for_each set element" error.

All 4 comments

I also tried:

variable "datalab_user_list" {
    type = list(string)
    default = [ "" ]
}
resource "google_service_account" "datalab_service_account" {
    for_each = toset(compact(var.datalab_user_list))
    account_id = "datalab-${split("@", each.key)[0]}"
    project = google_project.hipaa_project.project_id
}

But that still throws a similar error:

Error: Invalid for_each set argument

  on .terraform/modules/hipaa_worker_project1/datalab.tf line 24, in resource "google_service_account" "datalab_service_account":
  24:     for_each = toset(compact(var.datalab_user_list))

The given "for_each" argument value is unsuitable: "for_each" supports maps
and sets of strings, but you have provided a set containing type dynamic.

Ahh, thanks for reporting this!

Indeed, this is a quirk caused by the fact that in toset([]) there are no elements to hint the function as to what the set element type should be, and so "dynamic" here really means "unknown".

For now I think the most reliable workaround would be to manually convert to a map instead of a set, which shouldn't run into the same problem because map keys are _always_ strings:

  for_each = { for v in var.datalab_user_list : v => v }

A conversion like the above is essentially what Terraform itself does when handling a set of strings, but it checks the set element type first to produce that "Invalid for_each set element" error.

This threw me off here too here https://github.com/hashicorp/terraform/issues/22622

I use a resource with count and then for_each those on another resource. If count is 0 it fails.

I think the fix could be for_each checks the length first and aborts when 0. If there are items, then check that they are strings.

I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

Was this page helpful?
0 / 5 - 0 ratings