kubernetes/kops · error
field %q in %s was not an object, was %T
Error message
field %q in %s was not an object, was %T
What it means
While walking the dotted field path, Reparse requires each intermediate value to be a map[string]interface{} so it can continue descending. If a segment exists but holds a scalar, list, or other non-object type, this error reports the field, full path, and the actual Go type found.
Source
Thrown at pkg/kubemanifest/manifest.go:233
return ""
}
return s
}
// Reparse parses a subfield from an object
func (m *Object) Reparse(obj interface{}, fields ...string) error {
humanFields := strings.Join(fields, ".")
current := m.data
for _, field := range fields {
v, found := current[field]
if !found {
return fmt.Errorf("field %q in %s not found", field, humanFields)
}
m, ok := v.(map[string]interface{})
if !ok {
return fmt.Errorf("field %q in %s was not an object, was %T", field, humanFields, v)
}
current = m
}
b, err := yaml.Marshal(current)
if err != nil {
return fmt.Errorf("error marshaling %s to yaml: %v", humanFields, err)
}
if err := yaml.Unmarshal(b, obj); err != nil {
return fmt.Errorf("error unmarshaling subobject %s: %v", humanFields, err)
}
return nil
}
// Set mutates a subfield to the newValue
func (m *Object) Set(newValue interface{}, fieldPath ...string) error {View on GitHub (pinned to 4c8573c808)
Solutions
- Adjust the fields path to stop before non-object segments (walk lists separately)
- Verify the manifest schema/version matches the expected nesting
- Filter objects to the intended kind before Reparse
- Inspect the manifest's structure at the reported path (the error prints the actual %T)
Example fix
// before: path walks into a list
obj.Reparse([]string{"spec","containers"}, &v) // containers is []interface{}
// after: reparse the pod spec level instead
obj.Reparse([]string{"spec","template","spec"}, &podSpec) Defensive patterns
Strategy: validation
Validate before calling
func pathIsObject(obj *kubemanifest.Object, path ...string) bool {
cur, _ := obj.ToJSONMap()
for i, f := range path {
v, ok := cur[f]
if !ok { return false }
if i == len(path)-1 { return true } // last segment may be target struct
m, ok := v.(map[string]interface{})
if !ok { return false }
cur = m
}
return true
}
Type guard
func isObjectMap(v interface{}) bool {
_, ok := v.(map[string]interface{})
return ok
}
Try / catch
err := obj.Reparse(fields, &target)
if err != nil && strings.Contains(err.Error(), "was not an object") {
return fmt.Errorf("unexpected manifest shape at %v: %w", fields, err)
}
Prevention
- Don't walk into list-typed fields with Reparse; handle slices separately
- Match field paths to the manifest's schema version
- Inspect the actual type printed in the error before changing paths
- Test Reparse against representative manifests per kind
When it happens
Trigger: Calling Reparse with a path where an intermediate segment is not a nested object — e.g. path spec.template on a manifest where template is a string, or path through a list-valued field (lists can't be traversed by map key).
Common situations: Wrong field path through schema versions where a field changed type; attempting to walk into arrays (e.g. spec.containers) which are slices, not maps; manifests produced by another tool with unexpected shapes.
Related errors
- field %q in %s not found
- expected v1.Pod object in manifest %s, found %T
- error parsing addons or manifest: %v
- failed to parse objects: %w
- failed to parse objects: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/88a51b7f88450450.
Report an issue: GitHub.