{"record":{"id":"351b143437ddef8a","repo":"kubernetes/kops","slug":"only-accepts-structs-got-t","errorCode":null,"errorMessage":"only accepts structs; got %T","messagePattern":"only accepts structs; got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/configbuilder/buildconfigfile.go","lineNumber":103,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn configFile, nil\n}\n\nfunc getValueFromStruct(keyWithDots string, object interface{}) (*reflect.Value, error) {\n\tkeySlice := strings.Split(keyWithDots, \".\")\n\tv := reflect.ValueOf(object)\n\t// iterate through field names, ignoring the first name as it might be the current instance name\n\t// you can make it recursive also if want to support types like slice,map etc along with struct\n\tfor _, key := range keySlice {\n\t\tfor v.Kind() == reflect.Ptr {\n\t\t\tv = v.Elem()\n\t\t}\n\t\t// we only accept structs\n\t\tif v.Kind() != reflect.Struct {\n\t\t\treturn nil, fmt.Errorf(\"only accepts structs; got %T\", v)\n\t\t}\n\t\tv = v.FieldByName(key)\n\t}\n\n\treturn &v, nil\n}\n","sourceCodeStart":85,"sourceCodeEnd":110,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/configbuilder/buildconfigfile.go#L85-L110","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nFeatureGates map[string]string `json:\"featureGates,omitempty\" configfile:\"feature-gates.enabled\"`\n// after (maps are not traversable; address the struct directly or drop the tag)\nFeatureGates map[string]string `json:\"featureGates,omitempty\" configfile:\"-\"`","handlingStrategy":"type-guard","validationCode":"func isStructLike(x interface{}) bool {\n\tv := reflect.ValueOf(x)\n\tfor v.Kind() == reflect.Ptr { v = v.Elem() }\n\treturn v.Kind() == reflect.Struct\n}","typeGuard":"func ensureStruct(v reflect.Value) (reflect.Value, error) {\n\tfor v.Kind() == reflect.Ptr {\n\t\tif v.IsNil() { return v, fmt.Errorf(\"nil pointer in path\") }\n\t\tv = v.Elem()\n\t}\n\tif v.Kind() != reflect.Struct {\n\t\treturn v, fmt.Errorf(\"only accepts structs; got %s\", v.Kind())\n\t}\n\treturn v, nil\n}","tryCatchPattern":"v, err := getValueFromStruct(key, obj)\nif err != nil {\n\t// \"only accepts structs; got %T\" — check the segment of the dotted path that went off-struct\n\treturn fmt.Errorf(\"field path %q invalid for target: %w\", key, err)\n}","preventionTips":["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"],"tags":["reflection","struct-tags","go","config-generation"],"backgroundTag":"reflect-field-lookup-on-non-struct","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}