kubernetes/kops · error
expected slice, got %T
Error message
expected slice, got %T
What it means
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).
Source
Thrown at pkg/client/simple/vfsclientset/commonvfs.go:233
}
func (c *VFSClientBase) listNames(ctx context.Context) ([]string, error) {
keys, err := listChildNames(ctx, c.basePath)
if err != nil {
return nil, fmt.Errorf("error listing %s in state store: %v", c.kind, err)
}
// Seems to be an assumption in k8s APIs that items are always returned sorted
sort.Strings(keys)
return keys, nil
}
func (c *VFSClientBase) readAll(ctx context.Context, items interface{}) (interface{}, error) {
sliceValue := reflect.ValueOf(items)
sliceType := reflect.TypeOf(items)
if sliceType.Kind() != reflect.Slice {
return nil, fmt.Errorf("expected slice, got %T", items)
}
names, err := c.listNames(ctx)
if err != nil {
return nil, err
}
for _, name := range names {
o, err := c.Find(ctx, name)
if err != nil {
return nil, err
}
if o == nil {
return nil, fmt.Errorf("%s was listed, but then not found %q", c.kind, name)
}
sliceValue = reflect.Append(sliceValue, reflect.ValueOf(o).Elem())View on GitHub (pinned to 4c8573c808)
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.
Example fix
// before var out kops.InstanceGroup items, err := c.readAll(ctx, &out) // after var out kops.InstanceGroupList items, err := c.readAll(ctx, &out)
Defensive patterns
Strategy: type-guard
Validate before calling
func isListPointer(items interface{}) bool {
t := reflect.TypeOf(items)
return t != nil && t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct && strings.HasSuffix(t.Elem().Name(), "List")
}
if !isListPointer(items) { return fmt.Errorf("items must be *<Kind>List") } Type guard
func isSlice(v interface{}) bool {
return v != nil && reflect.TypeOf(v).Kind() == reflect.Ptr && reflect.TypeOf(v).Elem().Kind() == reflect.Slice
} Try / catch
items, err := c.readAll(ctx, &kops.InstanceGroupList{})
if err != nil {
if strings.Contains(err.Error(), "expected slice") {
return fmt.Errorf("caller bug: items must be a *KindList pointer")
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Custom/forked clientset code wiring List incorrectly; refactoring that changed the List item type; passing a single object where a List type is expected.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- unknown write option: %q
- duplicate scope: %q
- ResourceVersion not supported in InstanceGroupVFS::Get
- conversion error for field %s: %s
- unable to convert from Quantity %v to float
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/709e6f7926331a9b.
Report an issue: GitHub.