Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hint about failed conversion to list when returning error about mismatched tuple types in conditional #32301

Open
skeggse opened this issue Nov 29, 2022 · 2 comments
Labels
config enhancement hcl Use in conjunction with "upstream" when HCL is the relevant upstream upstream

Comments

@skeggse
Copy link

skeggse commented Nov 29, 2022

Terraform Version

Terraform v1.3.5
on darwin_amd64

Terraform Configuration Files

output "good_message" {
  value = flatten([
    for n in [{ o = [1] }, { o = [2] }] :
    n.o[0] == 1
    ? [n]
    : [merge({ a = 1 }, n)]
  ])
}

output "bad_message" {
  value = flatten([
    for n in [{ o = [1] }, { o = [2] }] :
    n.o[0] == 1
    ? [n]
    : [for k in [1, 3] : merge({ a = k }, n)]
  ])
}

Debug Output

not enabling TF_LOG because it's not necessary for this report.

$ tf validate
╷
│ Error: Inconsistent conditional result types
│
│   on main.tf line 26, in output "good_message":
│   25:     n.o[0] == 1
│   26:     ? [n]
│   27:     : [merge({ a = 1 }, n)]
│     ├────────────────
│     │ n.o[0] is 1
│
│ The true and false result expressions must have consistent types. Type mismatch for tuple element 0: The 'false' value includes object attribute "a", which is absent in the 'true' value.
╵
╷
│ Error: Inconsistent conditional result types
│
│   on main.tf line 26, in output "good_message":
│   25:     n.o[0] == 1
│   26:     ? [n]
│   27:     : [merge({ a = 1 }, n)]
│     ├────────────────
│     │ n.o[0] is 2
│
│ The true and false result expressions must have consistent types. Type mismatch for tuple element 0: The 'false' value includes object attribute "a", which is absent in the 'true' value.
╵
╷
│ Error: Inconsistent conditional result types
│
│   on main.tf line 35, in output "bad_message":
│   34:     n.o[0] == 1
│   35:     ? [n]
│   36:     : [for k in [1, 3] : merge({ a = k }, n)]
│     ├────────────────
│     │ n.o[0] is 1
│
│ The true and false result expressions must have consistent types. The 'true' tuple has length 1, but the 'false' tuple has length 2.
╵
╷
│ Error: Inconsistent conditional result types
│
│   on main.tf line 35, in output "bad_message":
│   34:     n.o[0] == 1
│   35:     ? [n]
│   36:     : [for k in [1, 3] : merge({ a = k }, n)]
│     ├────────────────
│     │ n.o[0] is 2
│
│ The true and false result expressions must have consistent types. The 'true' tuple has length 1, but the 'false' tuple has length 2.
╵

Expected Behavior

An error message for bad_message explaining that the problem was a missing field:

╷
│ Error: Inconsistent conditional result types
│
│   on main.tf line 35, in output "bad_message":
│   34:     n.o[0] == 1
│   35:     ? [n]
│   36:     : [for k in [1, 3] : merge({ a = k }, n)]
│     ├────────────────
│     │ n.o[0] is 1
│
│ The true and false result expressions must have consistent types. Type mismatch for tuple element 0: The 'false' value includes object attribute "a", which is absent in the 'true' value.
╵

Actual Behavior

The following error message, which, when embedded deep inside a for_each clause makes debugging pretty tricky.

╷
│ Error: Inconsistent conditional result types
│
│   on main.tf line 35, in output "bad_message":
│   34:     n.o[0] == 1
│   35:     ? [n]
│   36:     : [for k in [1, 3] : merge({ a = k }, n)]
│     ├────────────────
│     │ n.o[0] is 1
│
│ The true and false result expressions must have consistent types. The 'true' tuple has length 1, but the 'false' tuple has length 2.
╵

Steps to Reproduce

  1. terraform init
  2. terraform validate (or terraform plan)

Additional Context

No response

References

No response

@skeggse skeggse added bug new new issue not yet triaged labels Nov 29, 2022
@crw
Copy link
Collaborator

crw commented Dec 3, 2022

Thanks for this report!

@apparentlymart apparentlymart added the v1.3 Issues (primarily bugs) reported against v1.3 releases label Feb 3, 2023
@apparentlymart
Copy link
Member

Hi @skeggse!

Looking at the expression you wrote in bad_message, it seems like this error message is correct because:

  • The two arms of the conditional have tuple types, but not the same tuple type.
  • The tuple element types are not compatible with one another, so Terraform cannot automatically coerce this into a list of objects.
  • Tuple types are not required to have homogeneous element types -- that's what differentiates tuple types from list types -- and so neither of the conditional arms are invalid when taken in isolation.

Because Terraform's attempts to guess what you might have meant and apply implicit type conversions failed, Terraform just fell back on returning the most direct description of the original problem: the conditional expression arms are of different tuple types.

While I can use my human intuition to infer from the context what you intended this expression to mean, I'm not sure how to express that as a rule we could write in code to produce the error message you proposed. It would require Terraform to guess that you intended these tuples to be converted to lists and that it's the failure to convert to list that was the problem, not the direct type inconsistency.

Being explicit that the conditional result arms are supposed to be lists gives Terraform the extra hint required to get the error message you wanted:

> flatten([
:     for n in [{ o = [1] }, { o = [2] }] :
:     n.o[0] == 1
:     ? tolist([n])
:     : tolist([for k in [1, 3] : merge({ a = k }, n)])
:   ])
╷
│ Error: Inconsistent conditional result types
│ 
│   on <console-input> line 4:
│   (source code not available)
│ 
│ The true and false result expressions must have consistent types. Mismatched list element types: The 'false' value includes object attribute "a",
│ which is absent in the 'true' value.
╵

...but without that hint Terraform concludes that you must've intended the results to be tuples, because the automatic conversion to list failed.

I agree that what happened here isn't ideal, but I'm not really sure what to do about it. The best idea I have is to extend the error message to explicitly acknowledge the failed attempt at type conversion somehow. For example:

The true and false result expressions must have consistent types. The 'true' tuple has length 1, but the 'false' tuple has length 2. The tuples have mismatched element types, so automatic conversion to list is also impossible.

We've run into trouble in the past putting this sort of extra content in error messages because folks who only skim error messages tend to shut off and fail to process the message at all when there's more than one possibility to consider. But perhaps it would be okay in this case, since I'd imagine that intent to convert to a list is the more likely case than trying to select between two different tuple types.

(This error message actually belongs to HCL rather than to Terraform, so if we choose to make a change like I described above then we'll need to do it in the HCL repository rather than here.)

@apparentlymart apparentlymart added enhancement upstream config hcl Use in conjunction with "upstream" when HCL is the relevant upstream and removed bug new new issue not yet triaged v1.3 Issues (primarily bugs) reported against v1.3 releases labels May 17, 2024
@apparentlymart apparentlymart changed the title Misleading ternary type error message Hint about failed conversion to list when returning error about mismatched tuple types in conditional May 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
config enhancement hcl Use in conjunction with "upstream" when HCL is the relevant upstream upstream
Projects
None yet
Development

No branches or pull requests

3 participants