Leaving the object “b” empty, terraform returns error
...
pol_grp = {
a = { pol1 = "arn:aws:iam::aws:policy/IAMReadOnlyAccess",
pol2 = "arn:aws:iam::aws:policy/AmazonRoute53ReadOnlyAccess" }
b = {}
}
│ Error: Invalid function argument
│ 135: pols = tomap({
│ 136: for gk, group in local.pol_grp : gk => tomap({
│ 137: for pk, arn in group : pk => {
│ 138: arn = arn
│ 139: }
│ 140: })
│ 141: })
│ ├────────────────
│ │ local.pol_grp is object with 2 attributes
│ Invalid value for "v" parameter: cannot convert object to map of any single
│ type.
I suppose because tomap of an empty object. I know that removing empty “b” object completely will avoid this error but for a matter of interest to know how terrafom work on this case I tried to limit the for loop to discard empty objects before tomap using length functionwithout success:
...
pols = tomap({
for gk, group in local.pol_grp : gk => tomap({
for pk, arn in group : pk => {
arn = arn
}
})
if length(gk) > 0
})
...
I’m doing probably wrong assumptions and so:
What it means value for "v" parameter
What it menas cannot convert object to map of any single type
Am I doing wrong assumption on if condition param data type ? (not an object but a string) or something like that. How can I avoid error making more robust pols definition instead of imposing not empty objects ?
What you are running into here is a limitation of Terraform’s ability to convert types implicitly, or maybe just a limitation of the tomap function itself. The v here is the tomap argument, and it’s failing to find a usable type for the map, probably because of the nesting.
The conversion is possible here, so I’m not sure offhand where the failure is happening, but a map(map(map(string))) is a single map type which satisfies the data given. You would get the desired output by routing the value through a module variable with the exact type defined, for example:
variable "mapify" {
type = map(map(map(string)))
}
output "mapified" {
value = var.mapify
}
This may be a fixable bug in the tomap function, however that is only going to be able to go so far. There are a number of difficult to resolve type inference cases already, and it will probably require a new method for type specification or in-line conversion to fully resolve.
Hi @jbardin,
probably I’m missing something here because I’m not sure about error interpetation as type conversion issue as this pol_grp definition works:
pol_grp = {
a = { pol1 = "arn:aws:iam::aws:policy/IAMReadOnlyAccess",
pol2 = "arn:aws:iam::aws:policy/AmazonRoute53ReadOnlyAccess" }
b = {}
}
and the data structure is the same, with only the second code sample with an empty object (b={}).
For that very reason I thought the problem was related to presence of the empty object and I focused on the empty object exclusion attempt from the for loops (using if length(gk) > 0).
If I’m missing something and your are right, how and what I can cast to avoid the error in this sample (code inside locals section with no declared/defined variables).
I initially tried if condition on value (group) instead of key (gk), so not sure why in the first try the if on group didn’t work and I give a try on key (gk)…
Now I found that that solution works well using `if condition with length function on object value :
...
pols = tomap({
for gk, group in local.pol_grp : gk => tomap({
for pk, arn in group : pk => {
arn = arn
}
})
if length(group) > 0
})
...
as expected the if condition exclude empty objects so tomap return expected output: