kubernetes/kops · error
only accepts structs; got %T
Error message
only accepts structs; got %T
What it means
getValueFromStruct walks a dotted key path through a struct using reflection, dereferencing pointers along the way. If, after dereferencing, the current value is not a struct (and cannot be indexed further by field name), it returns this error. It exists because FieldByName only works on struct kinds.
Source
Thrown at pkg/configbuilder/buildconfigfile.go:103
if err != nil {
return nil, err
}
return configFile, nil
}
func getValueFromStruct(keyWithDots string, object interface{}) (*reflect.Value, error) {
keySlice := strings.Split(keyWithDots, ".")
v := reflect.ValueOf(object)
// iterate through field names, ignoring the first name as it might be the current instance name
// you can make it recursive also if want to support types like slice,map etc along with struct
for _, key := range keySlice {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
// we only accept structs
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("only accepts structs; got %T", v)
}
v = v.FieldByName(key)
}
return &v, nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Verify each segment of the dotted tag path resolves to a struct until the final segment
- Update the configfile tag to match the current (possibly changed) shape of the target struct
- Ensure the `target` argument passed to BuildConfigYaml is a pointer to a struct, not a map or slice
- If the source field legitimately became a non-struct, remove or rework the tag since dotted traversal only supports nested structs
Example fix
// before FeatureGates map[string]string `json:"featureGates,omitempty" configfile:"feature-gates.enabled"` // after (maps are not traversable; address the struct directly or drop the tag) FeatureGates map[string]string `json:"featureGates,omitempty" configfile:"-"`
Defensive patterns
Strategy: type-guard
Validate before calling
func isStructLike(x interface{}) bool {
v := reflect.ValueOf(x)
for v.Kind() == reflect.Ptr { v = v.Elem() }
return v.Kind() == reflect.Struct
} Type guard
func ensureStruct(v reflect.Value) (reflect.Value, error) {
for v.Kind() == reflect.Ptr {
if v.IsNil() { return v, fmt.Errorf("nil pointer in path") }
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return v, fmt.Errorf("only accepts structs; got %s", v.Kind())
}
return v, nil
} Try / catch
v, err := getValueFromStruct(key, obj)
if err != nil {
// "only accepts structs; got %T" — check the segment of the dotted path that went off-struct
return fmt.Errorf("field path %q invalid for target: %w", key, err)
} Prevention
- Only use dotted configfile paths through nested structs; handle maps/slices separately or skip them
- Validate the target argument is a pointer-to-struct before calling the builder
- After upstream struct changes, re-run TestGetStructVal/TestWrongStructField-style path tests
- Check each path segment's Kind before FieldByName when debugging
When it happens
Trigger: The dotted path in a configfile tag traverses into a map, slice, interface, or basic type before a remaining key is looked up (e.g. tag "foo.bar" where foo resolves to a map or a string); or the target passed to getValueFromStruct is not a struct/pointer-to-struct at all.
Common situations: A configfile tag path written for a nested struct now points at a field that upstream changed to a map or scalar; test cases (TestWrongStructField) exercising wrong field paths; passing a non-struct target struct into the config builder.
Related errors
- conversion error for field %s: %s
- unable to convert from Quantity %v to float
- BuildFlagsList to reflect value: %s
- cannot parse flag spec: %q
- unhandled type %v %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/351b143437ddef8a.
Report an issue: GitHub.