The true and false result expressions must have consistent types. both are arrays different size

services = local.accounts.lumin_academy_account == local.account_id ? jsondecode(file(“configurations/ecs/services/academy.json”)) : local.accounts.lumin_production_account == local.account_id ? jsondecode(file(“configurations/ecs/services/primary.json”)) : jsondecode(file(“configurations/ecs/services/lumin-sandbox.json”))
|----------------
| local.accounts.lumin_academy_account is “xxxxxxxx”
| local.accounts.lumin_production_account is “xxxxxxxxx”

The true and false result expressions must have consistent types. The given
expressions are tuple and list of object, respectively.
Both results are arrays of objects, however, i noticed when one array have two objects and the other have one, terraform throws the above exception.

Hi @fosovia,

Because JSON allows arrays with mixed element types, whereas Terraform’s type system expects lists to have homogenous elements, the jsondecode function translates JSON arrays into the Terraform language’s tuple types, as we can see in the error message here.

Terraform attempts to automatically resolve this problem by converting both of the potential results of the conditional expression to be lists where possible, which I think explains why the inner of your two conditional expressions here is showing in the error message as “list of object”, but the automatic conversion doesn’t seem to have worked for the other one and so Terraform returned this error.

In situations like this, where automatic type inference doesn’t succeed, it can be helpful to add explicit type conversions to explain your intent to Terraform, and then Terraform can often give a more specific error message based on that additional information. In this case I would start by explicitly converting all of the jsondecode results to be lists and then we should be able to see which one doesn’t succeed, and hopefully get a further hint as to why it didn’t succeed:

  services = (
    local.accounts.lumin_academy_account == local.account_id ?
    tolist(jsondecode(file("configurations/ecs/services/academy.json"))) :
    (
      local.accounts.lumin_production_account == local.account_id ?
      tolist(jsondecode(file("configurations/ecs/services/primary.json"))) :
      tolist(jsondecode(file("configurations/ecs/services/lumin-sandbox.json")))
    )
  )

Another way to go here would be to reformulate this so that deciding on the filename is a separate step from actually loading and parsing the file. That way it won’t matter what data type each JSON file produces, because the conditions will only be working with filename strings and not with the actual data:

locals {
  services_filename = (
    local.accounts.lumin_academy_account == local.account_id ?
    "academy.json" :
    (
      local.accounts.lumin_production_account == local.account_id ?
      "primary.json" :
      "lumin-sandbox.json"
    )
  )
  services = jsondecode(file("${path.module}/configurations/ecs/services/${local.services_filename}"))
}

With the above approach. local.services would be the result of parsing whichever file that local.services_filename selected, giving directly the jsondecode result without any automatic type conversions. However, that does mean that expressions elsewhere which make use of local.services must be robust enough to handle all of the possible structures those files might have.