{"record":{"id":"2f2f02f35d182ba3","repo":"docker/cli","slug":"expected-a-map-or-a-list-got-t-v","errorCode":null,"errorMessage":"expected a map or a list, got %T: %#v","messagePattern":"expected a map or a list, got %T: %#v","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cli/compose/loader/loader.go","lineNumber":847,"sourceCode":"\t\t\tfor i, allowSep := range allowSeps {\n\t\t\t\tentry := fmt.Sprint(entry)\n\t\t\t\tk, v, ok := strings.Cut(entry, allowSep)\n\t\t\t\tif ok {\n\t\t\t\t\t// Entry uses this allowed separator. Add it to the result, using\n\t\t\t\t\t// sep as a separator.\n\t\t\t\t\tresult = append(result, fmt.Sprintf(\"%s%s%s\", k, sep, v))\n\t\t\t\t\tbreak\n\t\t\t\t} else if i == len(allowSeps)-1 {\n\t\t\t\t\t// No more separators to try, keep the entry if allowNil.\n\t\t\t\t\tif allowNil {\n\t\t\t\t\t\tresult = append(result, k)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\tpanic(fmt.Errorf(\"expected a map or a list, got %T: %#v\", listOrMapping, listOrMapping))\n}\n\nfunc transformMappingOrListFunc(sep string, allowNil bool) TransformerFunc {\n\treturn func(data any) (any, error) {\n\t\treturn transformMappingOrList(data, sep, allowNil), nil\n\t}\n}\n\nfunc transformMappingOrList(mappingOrList any, sep string, allowNil bool) any {\n\tswitch values := mappingOrList.(type) {\n\tcase map[string]any:\n\t\treturn toMapStringString(values, allowNil)\n\tcase []any:\n\t\tresult := make(map[string]any)\n\t\tfor _, v := range values {\n\t\t\tkey, val, hasValue := strings.Cut(v.(string), sep)\n\t\t\tswitch {\n\t\t\tcase !hasValue && allowNil:","sourceCodeStart":829,"sourceCodeEnd":865,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/compose/loader/loader.go#L829-L865","documentation":"This is a PANIC, not a returned error. transformListOrMapping (used by hosts/extra_hosts/dns list forms) only handles `map[string]any` and `[]any`; any other type calls panic(). Because Load() does not recover, the panic crashes the process. Callers must ensure the field is a map or list before it reaches the transformer.","triggerScenarios":"A field routed through transformListOrMapping receives a scalar (e.g. `extra_hosts: host1` as a bare string) or null. The function has no default branch — it panics.","commonSituations":"Mis-typing a list field as a scalar; templating emitting null; downstream code calling the transformer directly with a non-conforming value.","solutions":["Provide a list or mapping for the field, e.g. `extra_hosts: [\"host1:1.2.3.4\"]`.","If calling the loader programmatically, wrap Load()/Transform() in a recover() to convert the panic into an error."],"exampleFix":"# before\nweb:\n  extra_hosts: host1\n# after\nweb:\n  extra_hosts:\n    - \"host1:10.0.0.1\"","handlingStrategy":"try-catch","validationCode":"// transformListOrMapping panics on non-map/non-list; pre-check the field.\nfunc validateListOrMapping(field string, v any) error {\n    switch v.(type) {\n    case map[string]any, []any:\n        return nil\n    default:\n        return fmt.Errorf(\"%s must be a mapping or list, got %T\", field, v)\n    }\n}","typeGuard":"func isMapOrList(v any) bool {\n    switch v.(type) {\n    case map[string]any, []any:\n        return true\n    }\n    return false\n}","tryCatchPattern":"// Load() does not recover; wrap it when calling programmatically.\nfunc safeLoad(details types.ConfigDetails) (cfg *types.Config, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"compose load panic: %v\", r)\n        }\n    }()\n    return Load(details)\n}","preventionTips":["This error is a panic — always guard programmatic loader calls with recover().","Ensure hosts/extra_hosts/dns-style fields are lists or maps.","Add `docker compose config` as a CI gate to catch malformed fields."],"tags":["compose","panic","type-mismatch","list","hosts"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}