hashicorp/terraform · error
input must be a map of lists of strings
Error message
input must be a map of lists of strings
What it means
Thrown by `transpose()` (TransposeFunc) when an inner-list element's type is not exactly cty.String. transpose() is typed as map(list(string)) and each value becomes a string key in the output map, so non-string elements (numbers, bools) are rejected even though the declared type permits the map(list(...)) shape. The check uses val.Type().Equals(cty.String).
Solutions
- Convert inner elements to strings: `{ for k, v in var.m : k => [for x in v : tostring(x)] }`.
- Declare the variable type strictly as map(list(string)) so mismatches surface earlier.
- Re-type the upstream data source to emit strings.
Example fix
// before
locals { t = transpose(var.ids) } # var.ids is map(list(any)) with numbers
// after
locals { t = transpose({ for k, v in var.ids : k => [for x in v : tostring(x)] }) } Defensive patterns
Strategy: validation
Validate before calling
# HCL: stringify inner elements before transpose
locals { t = transpose({ for k, v in var.m : k => [for x in v : tostring(x)] }) } Type guard
# HCL: declare strictly typed variable
variable "m" { type = map(list(string)) } Prevention
- Declare the variable as map(list(string)) so non-strings fail at validation.
- Convert inner elements with tostring() before transpose().
- Avoid loose map(list(any)) typings.
When it happens
Trigger: Calling transpose with a map whose inner lists hold non-strings, e.g. `transpose({a = [1, 2]})`. A variable declared loosely as map(list(any)) fed numeric values.
Common situations: Loosely typed variables (map(list(any))) that happen to carry numbers. Data from a datasource where the inner element type is number rather than string.
Related errors
- argument must be a list or tuple
- argument must be a string, a collection type, or a…
- input list must not contain null string
- input must not contain null list
- all arguments must have the same type
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/f97dbc2f224a9e5d.
Report an issue: GitHub.
Appendix: source
Thrown at internal/lang/funcs/collection.go:594
if !inputMap.IsWhollyKnown() {
return cty.UnknownVal(retType), nil
}
outputMap := make(map[string]cty.Value)
tmpMap := make(map[string][]string)
for it := inputMap.ElementIterator(); it.Next(); {
inKey, inVal := it.Element()
if inVal.IsNull() {
return cty.MapValEmpty(cty.List(cty.String)), errors.New("input must not contain null list")
}
for iter := inVal.ElementIterator(); iter.Next(); {
_, val := iter.Element()
if val.IsNull() {
return cty.MapValEmpty(cty.List(cty.String)), errors.New("input list must not contain null string")
}
if !val.Type().Equals(cty.String) {
return cty.MapValEmpty(cty.List(cty.String)), errors.New("input must be a map of lists of strings")
}
outKey := val.AsString()
if _, ok := tmpMap[outKey]; !ok {
tmpMap[outKey] = make([]string, 0)
}
outVal := tmpMap[outKey]
outVal = append(outVal, inKey.AsString())
sort.Strings(outVal)
tmpMap[outKey] = outVal
}
}
for outKey, outVal := range tmpMap {
values := make([]cty.Value, 0)
for _, v := range outVal {
values = append(values, cty.StringVal(v))
}View on GitHub (pinned to d32a084675)