{"record":{"id":"839d0a80c911a69b","repo":"docker/cli","slug":"expected-slice-got-t","errorCode":null,"errorMessage":"expected slice, got %T","messagePattern":"expected slice, got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"templates/templates.go","lineNumber":137,"sourceCode":"\t\tfor i := range rv.Len() {\n\t\t\tif i > 0 {\n\t\t\t\tb.WriteString(sep)\n\t\t\t}\n\t\t\t_, _ = fmt.Fprint(&b, rv.Index(i).Interface())\n\t\t}\n\t\treturn b.String(), nil\n\n\tcase reflect.Map:\n\t\tvar out []string\n\t\tfor _, k := range rv.MapKeys() {\n\t\t\tout = append(out, fmt.Sprint(rv.MapIndex(k).Interface()))\n\t\t}\n\t\t// Not ideal, but trying to keep a consistent order\n\t\tsort.Strings(out)\n\t\treturn strings.Join(out, sep), nil\n\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"expected slice, got %T\", elems)\n\t}\n}\n","sourceCodeStart":119,"sourceCodeEnd":140,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/templates/templates.go#L119-L140","documentation":"Returned by the 'join' template function (joinElements, used in docker --format Go templates and the table headers) when the argument piped to join is not nil, not a []string, and not an array, slice, or map. reflect.ValueOf(...).Kind() falls into the default branch and reports the actual Go type via %T.","triggerScenarios":"Using '{{join .Field \",\"}}' in a '--format' template where .Field is a scalar (string, int, bool) or a struct rather than a slice/array/map. For example '{{join .Image \",\"}}' on a string field, or piping an integer.","commonSituations":"Authoring a custom --format and assuming a field is a list when the inspect JSON shows a string; piping the wrong sub-field; or using join on a single value that is not a collection.","solutions":["Confirm the field is a slice/array/map in 'docker inspect --format \"{{json .}}\"' output before joining.","If the field is a scalar string, drop join and use it directly: '{{.Image}}'.","Wrap the value so join receives a slice, or pick the correct list-valued field (e.g. .Mounts, .Config.Env)."],"exampleFix":"# before\n# .RepoTags is a []string -> OK; but piping a string field fails:\ndocker image ls --format '{{join .ID \",\"}}'\n# after: join a real slice field\ndocker image ls --format '{{join .RepoTags \",\"}}'","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// joinElements accepts: nil, []string, arrays, slices, maps. Guard everything else out.\nimport \"reflect\"\n\nfunc isJoinable(v any) bool {\n    if v == nil { return true }\n    if _, ok := v.([]string); ok { return true }\n    switch reflect.ValueOf(v).Kind() {\n    case reflect.Array, reflect.Slice, reflect.Map:\n        return true\n    }\n    return false\n}\n\n// usage before rendering:\n// if !isJoinable(field) { /* don't call {{join field}}; render it directly */ }","tryCatchPattern":"var buf bytes.Buffer\nif err := tmpl.Execute(&buf, data); err != nil {\n    // err text: expected slice, got <typename>\n    return fmt.Errorf(\"template error (is the joined field a slice?): %w\", err)\n}","preventionTips":["Inspect the data shape first: 'docker <obj> inspect --format \"{{json .}}\"'.","Only join fields that are arrays/slices/maps; render scalars directly.","Remember HeaderFunctions overrides 'join' to take a string — only the body 'join' requires a slice."],"tags":["docker","templates","format","go-template","reflection"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}