"Invalid for_each argument" with merge

Hi all,

I still have issues with Terraform failing with Invalid for_each argument. Even after following GH#23052 and GH#22735 I don’t really understand what causes this.

Version:

Terraform v0.12.20
+ provider.null v2.1.2

Here is an really trivial example to reproduce:

resource "null_resource" "one" {
  for_each = { "test1" = 1, "test2" = 2, "test3" = 3 }
}

resource "null_resource" "two" {
  for_each = { "test4" = 1, "test5" = 2, "test6" = 3 }
}

resource "null_resource" "from_one" {
  for_each = null_resource.one
}

resource "null_resource" "from_two" {
  for_each = null_resource.two
}

resource "null_resource" "from_both" {
  for_each = merge(null_resource.one, null_resource.two)
}

which gives:

Error: Invalid for_each argument

  on main.tf line 18, in resource "null_resource" "from_both":
  18:   for_each = merge(
  19:     null_resource.one,
  20:     null_resource.two
  21:   )

The "for_each" 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 for_each depends on.

The point is: null_resource.from_one and null_resource.from_two alone work without issues, just null_resource.from_both with the merge() does not. Therefore I don’t see how this can be related to any unknown key/value, as both alone work.

Any ideas, what I’m doing wrong?

Here is the working sample:

resource "null_resource" "one" {
  for_each = { "test1" = 1, "test2" = 2, "test3" = 3 }
}

resource "null_resource" "two" {
  for_each = { "test4" = 1, "test5" = 2, "test6" = 3 }
}

resource "null_resource" "from_one" {
  for_each = null_resource.one
}

resource "null_resource" "from_two" {
  for_each = null_resource.two
}

#resource "null_resource" "from_both" {
#  for_each = merge(null_resource.one, null_resource.two)
#}

And the output:

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.from_one["test1"] will be created
  + resource "null_resource" "from_one" {
      + id = (known after apply)
    }

  # null_resource.from_one["test2"] will be created
  + resource "null_resource" "from_one" {
      + id = (known after apply)
    }

  # null_resource.from_one["test3"] will be created
  + resource "null_resource" "from_one" {
      + id = (known after apply)
    }

  # null_resource.from_two["test4"] will be created
  + resource "null_resource" "from_two" {
      + id = (known after apply)
    }

  # null_resource.from_two["test5"] will be created
  + resource "null_resource" "from_two" {
      + id = (known after apply)
    }

  # null_resource.from_two["test6"] will be created
  + resource "null_resource" "from_two" {
      + id = (known after apply)
    }

  # null_resource.one["test1"] will be created
  + resource "null_resource" "one" {
      + id = (known after apply)
    }

  # null_resource.one["test2"] will be created
  + resource "null_resource" "one" {
      + id = (known after apply)
    }

  # null_resource.one["test3"] will be created
  + resource "null_resource" "one" {
      + id = (known after apply)
    }

  # null_resource.two["test4"] will be created
  + resource "null_resource" "two" {
      + id = (known after apply)
    }

  # null_resource.two["test5"] will be created
  + resource "null_resource" "two" {
      + id = (known after apply)
    }

  # null_resource.two["test6"] will be created
  + resource "null_resource" "two" {
      + id = (known after apply)
    }

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

------------------------------------------------------------------------

Hi,

Thanks for the excellent example. I think some details were lost due to the many confounding factors in the linked issues, but I agree that this configuration appears at first glance that it should work.

While it’s technically true that this isn’t expected to work at the moment due to one or more unknown values going into the merge function, I believe we can improve the map related functions to better handle the cases where the keys are all known (which is the requirement for for_each).

I opened an issue based on your example here: https://github.com/hashicorp/terraform/issues/24024

Thanks!

Hi,

thanks for clarifying the issue.

Do you know of any way to merge the result of the two “parent” resources before, or do I really have to duplicate null_resource.from_both to make this work?

Thanks!