Invalid function argument after 0.12 upgrade

Error: Invalid function argument

  on tf-modules/common/docker/install/output.tf line 2, in output "id":
   2:   value = "${join(",",null_resource.docker_installer[*].id)}"
    |----------------
    | null_resource.docker_installer is tuple with 1 element

Invalid value for "lists" parameter: element 0 is null; cannot concatenate
null values.

After upgrading from terraform 0.11.x to terraform 0.12.29 I get these errors, possibly related to how I use the “id” and maybe how we use lists as well. Any tips on addressing this?

We originally had

value = "${join(",",null_resource.docker_installer.*.id)}"

and changed it to

value = "${join(",",null_resource.docker_installer[*].id)}"

After reading some documentation around the splat expression but the error is the same either way

Hi @nicks1993!

Something pretty odd seems to be going on here… it seems like somehow one of your null_resource.docker_installer instances has null for its id attribute, but the null_resource resource type typically just writes in the timestamp of the last create into its id so it shouldn’t ever be null.

If you run terraform show, can you see null_resource.docker_installer instances in there? Are they null, or are they strings containing timestamps as expected?

@apparentlymart Thank for your response.

I actually have 2 issues that are very similar to each other.

so the first error is

Error: Provider produced inconsistent result after apply
When applying changes to
module.registry_docker.module.docker_install.null_resource.docker_installer_configurer,
provider "registry.terraform.io/-/null" produced an unexpected new value for
.id: was null, but now cty.StringVal("992243335272418932").
This is a bug in the provider, which should be reported in the provider's own
issue tracker.

so I checked the state file and got this

287        "name": "docker_installer_configurer",
   288        "provider": "provider.null",
   289        "instances": [
   290          {
   291            "status": "tainted",
   292            "schema_version": 0,
   293            "attributes": {
   294              "id": "992243335272418932",
   295              "triggers": null
   296            },

The second error is the same as my initial post

Error: Invalid function argument

  on tf-modules/common/docker/install/output.tf line 2, in output "id":
   2:   value = "${join(",",null_resource.docker_installer[*].id)}"
    |----------------
    | null_resource.docker_installer is tuple with 1 element

Invalid value for "lists" parameter: element 0 is null; cannot concatenate
null values.

I checked the statefile and found

       "module": "module.registry_docker.module.docker_install",
  "mode": "managed",
  "type": "null_resource",
  "name": "docker_installer_configurer",
  "provider": "provider.null",
  "instances": [
    {
      "status": "tainted",
      "schema_version": 0,
      "attributes": {
        "id": "992243335272418932",
        "triggers": null
      },
      "private": "bnVsbA==",
      "dependencies": [
        "module.registry_docker.module.docker_install.null_resource.docker_installer",
        "module.registry_docker.module.docker_install.null_resource.docker_installer_configure_external_registry",
        "module.registry_docker.module.docker_install.null_resource.docker_installer_configure_inner_registry"
      ]
    }
  ]
},

and

{
  "module": "module.registry_docker.module.docker_install",
  "mode": "managed",
  "type": "null_resource",
  "name": "docker_installer",
  "each": "list",
  "provider": "provider.null",
  "instances": []
},

so for this second block of code its pretty clear that there is no “id” field but I can’t seem to figure out what is going on here still

Hi @nicks1993,

I’m afraid I’m not familiar with this problem either, so I’m not sure how it’s arising. The message about the bug in the null provider seems to be the root cause here, where for some reason it’s setting id to null (rather than “unknown”) during planning, but I suspect that something more tricky is going on here because from what I know about the Terraform SDK it should be impossible for that attribute to be null.

I think in order to proceed with this we’ll need to treat is as a bug report, so that the broader Terraform Core team can look at it and try to reproduce it. It’d be very helpful if you would open a bug report issue and try as best you can to complete the questions in the new issue template so that the team has sufficient information to get started with investigation. Depending on what you’re able to share in the first issue, the team members might ask you some other questions in order to achieve the initial goal of being able to reliably reproduce the error in their development environments.

Thanks!

@apparentlymart My apologies, I’ve actually started over in the upgrade after realizing I didn’t do it correctly the first time.

The bug I get now is

Info: Check inner_registry module
Error: Invalid value for module argument
  on tf-modules/common/docker/main.tf line 33, in module "docker_install":
  33:   docker_removed_instances = module.docker_remove.removed_instances
The given value is not suitable for child module variable
"docker_removed_instances" defined at
tf-modules/common/docker/install/variables.tf:48,1-36: element 0: string
required.  

Some additional code related to this

output "removed_instances" {
  value = [null_resource.docker_remover.*.id]
}

variable "docker_removed_instances" {
  description = "docker action, allowed values: [install, remove, checker]"
  type        = list(string)
}

it appears that maybe it no longer returns a list of strings to the output variable?

changing

output "removed_instances" {
  value = [null_resource.docker_remover.*.id]
}

to

output "removed_instances" {
  value = null_resource.docker_remover[x].id
}

fixed it, is using that list syntax now invalid?

Hi @nicks1993,

The expression [null_resource.docker_remover.*.id] would return a list of lists, because the .* operator itself already produces a list, and then [ ... ] wraps it in another one.

I think you could address this by changing it to just null_resource.docker_remover.*.id.

You could also switch to the new-style splat syntax null_resource.docker_remover[*].id which is the more preferred one for 0.12 because its behavior is a little more consistent for more complex situations, but the two have identical behavior in this simple case so that would be only a cosmetic change, not a functional one.