A key collision
Two users share a first name, and the expression only fails once the data contains one
users = ["alice.smith", "bob.jones", "alice.chen"]
{ for u in users : split(".", u)[0] => u } Try a for expression against real data. The failure worth finding here is the one that only appears when two elements produce the same key, which small test data never does.
Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.
The answer appears here
Paste on the left and press Test. Nothing leaves this tab.
Nothing else to flag.
No formatting problems, and nothing the rules object to. Worth remembering what that covers: this reads the file you pasted, not the account or cluster it will be applied to.
No finding matches that filter.
Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.
Two users share a first name, and the expression only fails once the data contains one
users = ["alice.smith", "bob.jones", "alice.chen"]
{ for u in users : split(".", u)[0] => u }Collisions become lists, which changes the value type for whatever consumes it
users = ["alice.smith", "bob.jones", "alice.chen"]
{ for u in users : split(".", u)[0] => u... }Every key here becomes part of a resource address if this feeds a for_each
items = ["a", "b"]
{ for i in items : i => upper(i) }These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
Two elements produce the same key and Terraform stops, or with the grouping symbol they silently merge. Either way it appears the first time the data collides, long after the code was written.
Instead:Key by something unique by construction, such as an id, or add ... and handle the list.
The key is part of the resource address, so a change in list order renames every resource after the change, which Terraform reads as destroy and create.
Instead:Key by a stable attribute of the element itself.
Map iteration is by sorted key, so a list built from a map comes out sorted rather than in the order you wrote it.
Instead:Build the list directly if the order is meaningful.
It depends on which form you wrote, and the two forms look almost identical.
[for x in c : e] produces a list or set. { for k, v in c : k => v } produces a map. Only the map form can key a for_each meaningfully, and only the map form can produce a key collision.
Terraform reports that two elements produced the same key, and stops. That is the good outcome, and it only happens when the data actually collides, so an expression that works for months breaks when somebody adds a user whose first name matches another's.
{ for u in users : dept(u) => u... } collects everything sharing a key into a list rather than erroring. That changes the value type, so anything consuming it has to handle a list, which is the trade being made rather than a free fix.
If the result feeds a for_each, every key appears in state as resource["key"], in every plan line, and in every state command anyone types. A key derived from an index or from anything that changes destroys and recreates the resource when it changes.
[for x in c : x if cond]. It is easy to read as filtering the input; it filters the output, which matters when the value expression itself would fail on the elements being filtered out, because it still runs on them first.
Which means the output order of a list built from a map is sorted by key rather than by the order the map was written. For a list this is visible; for a map result it does not matter.