{"record":{"id":"709e6f7926331a9b","repo":"kubernetes/kops","slug":"expected-slice-got-t","errorCode":null,"errorMessage":"expected slice, got %T","messagePattern":"expected slice, got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/client/simple/vfsclientset/commonvfs.go","lineNumber":233,"sourceCode":"}\n\nfunc (c *VFSClientBase) listNames(ctx context.Context) ([]string, error) {\n\tkeys, err := listChildNames(ctx, c.basePath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error listing %s in state store: %v\", c.kind, err)\n\t}\n\n\t// Seems to be an assumption in k8s APIs that items are always returned sorted\n\tsort.Strings(keys)\n\n\treturn keys, nil\n}\n\nfunc (c *VFSClientBase) readAll(ctx context.Context, items interface{}) (interface{}, error) {\n\tsliceValue := reflect.ValueOf(items)\n\tsliceType := reflect.TypeOf(items)\n\tif sliceType.Kind() != reflect.Slice {\n\t\treturn nil, fmt.Errorf(\"expected slice, got %T\", items)\n\t}\n\n\tnames, err := c.listNames(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfor _, name := range names {\n\t\to, err := c.Find(ctx, name)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif o == nil {\n\t\t\treturn nil, fmt.Errorf(\"%s was listed, but then not found %q\", c.kind, name)\n\t\t}\n\n\t\tsliceValue = reflect.Append(sliceValue, reflect.ValueOf(o).Elem())","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/client/simple/vfsclientset/commonvfs.go#L215-L251","documentation":"readAll uses reflection and requires its items parameter to be a slice (pointer to a generated *<Kind>List type). Anything else fails this check. This is an internal contract violation by the caller of readAll (only List).","triggerScenarios":"A caller passes a non-slice (e.g. a pointer to a single object like &kops.Cluster instead of &kops.ClusterList) into VFSClientBase.readAll via List.","commonSituations":"Custom/forked clientset code wiring List incorrectly; refactoring that changed the List item type; passing a single object where a List type is expected.","solutions":["Pass a pointer to the generated *<Kind>List type from the kops API (e.g. &kops.InstanceGroupList{}).","Check the call site in List() to confirm the items argument type.","Fix any custom/forked code that changed the argument type."],"exampleFix":"// before\nvar out kops.InstanceGroup\nitems, err := c.readAll(ctx, &out)\n// after\nvar out kops.InstanceGroupList\nitems, err := c.readAll(ctx, &out)","handlingStrategy":"type-guard","validationCode":"func isListPointer(items interface{}) bool {\n    t := reflect.TypeOf(items)\n    return t != nil && t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct && strings.HasSuffix(t.Elem().Name(), \"List\")\n}\nif !isListPointer(items) { return fmt.Errorf(\"items must be *<Kind>List\") }","typeGuard":"func isSlice(v interface{}) bool {\n    return v != nil && reflect.TypeOf(v).Kind() == reflect.Ptr && reflect.TypeOf(v).Elem().Kind() == reflect.Slice\n}","tryCatchPattern":"items, err := c.readAll(ctx, &kops.InstanceGroupList{})\nif err != nil {\n    if strings.Contains(err.Error(), \"expected slice\") {\n        return fmt.Errorf(\"caller bug: items must be a *KindList pointer\")\n    }\n    return err\n}","preventionTips":["Always pass pointers to generated List types from the kops API","Keep readAll call sites covered by unit tests","Avoid custom reflection-based plumbing around the clientset"],"tags":["reflection","api-misuse","programming-error"],"backgroundTag":"invalid-argument-value","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}