{"record":{"id":"f97dbc2f224a9e5d","repo":"hashicorp/terraform","slug":"input-must-be-a-map-of-lists-of-strings","errorCode":null,"errorMessage":"input must be a map of lists of strings","messagePattern":"input must be a map of lists of strings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/collection.go","lineNumber":594,"sourceCode":"\t\tif !inputMap.IsWhollyKnown() {\n\t\t\treturn cty.UnknownVal(retType), nil\n\t\t}\n\n\t\toutputMap := make(map[string]cty.Value)\n\t\ttmpMap := make(map[string][]string)\n\n\t\tfor it := inputMap.ElementIterator(); it.Next(); {\n\t\t\tinKey, inVal := it.Element()\n\t\t\tif inVal.IsNull() {\n\t\t\t\treturn cty.MapValEmpty(cty.List(cty.String)), errors.New(\"input must not contain null list\")\n\t\t\t}\n\t\t\tfor iter := inVal.ElementIterator(); iter.Next(); {\n\t\t\t\t_, val := iter.Element()\n\t\t\t\tif val.IsNull() {\n\t\t\t\t\treturn cty.MapValEmpty(cty.List(cty.String)), errors.New(\"input list must not contain null string\")\n\t\t\t\t}\n\t\t\t\tif !val.Type().Equals(cty.String) {\n\t\t\t\t\treturn cty.MapValEmpty(cty.List(cty.String)), errors.New(\"input must be a map of lists of strings\")\n\t\t\t\t}\n\n\t\t\t\toutKey := val.AsString()\n\t\t\t\tif _, ok := tmpMap[outKey]; !ok {\n\t\t\t\t\ttmpMap[outKey] = make([]string, 0)\n\t\t\t\t}\n\t\t\t\toutVal := tmpMap[outKey]\n\t\t\t\toutVal = append(outVal, inKey.AsString())\n\t\t\t\tsort.Strings(outVal)\n\t\t\t\ttmpMap[outKey] = outVal\n\t\t\t}\n\t\t}\n\n\t\tfor outKey, outVal := range tmpMap {\n\t\t\tvalues := make([]cty.Value, 0)\n\t\t\tfor _, v := range outVal {\n\t\t\t\tvalues = append(values, cty.StringVal(v))\n\t\t\t}","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/lang/funcs/collection.go#L576-L612","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlocals { t = transpose(var.ids) }   # var.ids is map(list(any)) with numbers\n\n// after\nlocals { t = transpose({ for k, v in var.ids : k => [for x in v : tostring(x)] }) }","handlingStrategy":"validation","validationCode":"# HCL: stringify inner elements before transpose\nlocals { t = transpose({ for k, v in var.m : k => [for x in v : tostring(x)] }) }","typeGuard":"# HCL: declare strictly typed variable\nvariable \"m\" { type = map(list(string)) }","tryCatchPattern":null,"preventionTips":["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."],"tags":["terraform","hcl","collection-functions","transpose","type-check"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}