cilium/cilium · error
failed to decode non-Unstructured object
Error message
failed to decode non-Unstructured object
What it means
After confirming the object claims Table kind, unstructuredToTable requires the concrete Go type to be *unstructured.Unstructured so its raw map can be converted into metav1.Table. If the object is some other runtime.Object implementation, this error is returned. It signals a decoding/typing mismatch in the caller's pipeline.
Source
Thrown at cilium-cli/k8s/tables.go:20
// Copyright Authors of Cilium
package k8s
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)
func unstructuredToTable(o runtime.Object) (*metav1.Table, error) {
if metav1.SchemeGroupVersion.WithKind("Table") != o.GetObjectKind().GroupVersionKind() {
return nil, fmt.Errorf("failed to decode non-Table object")
}
u, ok := o.(*unstructured.Unstructured)
if !ok {
return nil, fmt.Errorf("failed to decode non-Unstructured object")
}
t := &metav1.Table{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, t); err != nil {
return nil, err
}
for i := range t.Rows {
row := &t.Rows[i]
if row.Object.Raw == nil || row.Object.Object != nil {
continue
}
converted, err := runtime.Decode(unstructured.UnstructuredJSONScheme, row.Object.Raw)
if err != nil {
return nil, err
}
row.Object.Object = converted
}
return t, nil
}View on GitHub (pinned to ac7b90affa)
Solutions
- Decode the response into unstructured.Unstructured (e.g. via runtime.DecodeInto with an unstructured decoder)
- Ensure the list request goes through the RESTClient returning unstructured data, not the typed clientset
- Convert the typed object to unstructured via runtime.DefaultUnstructuredConverter.ToUnstructured before passing
Example fix
// before
pods, _ := clientset.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{})
table, err := unstructuredSliceToTable([]runtime.Object{pods})
// after
u := &unstructured.Unstructured{}
untime.DefaultUnstructuredConverter.ToUnstructured(pods, &u.Object)
table, err := unstructuredSliceToTable([]runtime.Object{u}) Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := obj.(*unstructured.Unstructured); !ok {
return errors.New("object must be *unstructured.Unstructured for table conversion")
} Type guard
func isUnstructured(o runtime.Object) (*unstructured.Unstructured, bool) {
u, ok := o.(*unstructured.Unstructured)
return u, ok
} Try / catch
table, err := unstructuredToTable(o)
if err != nil && strings.Contains(err.Error(), "non-Unstructured") {
u := &unstructured.Unstructured{}
runtime.DefaultUnstructuredConverter.ToUnstructured(o, &u.Object)
table, err = unstructuredToTable(u)
} Prevention
- Keep table rendering on the unstructured/RESTClient path, not the typed clientset
- Convert typed objects with DefaultUnstructuredConverter before table conversion
- Centralize decoding in one place to avoid mixed types
When it happens
Trigger: Calling unstructuredToTable/unstructuredSliceToTable with an object that passed the Table GVK check but is a typed struct (e.g. *corev1.PodList) or a custom runtime.Object rather than *unstructured.Unstructured.
Common situations: Mixing typed clientset results into the unstructured table pipeline; custom decoders producing typed objects; refactoring that changed the decode path.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to set tls.caBundle.enabled for cluster %s: %w
- failed to set clustermesh.apiserver.podAnnotations for clust
- failed to convert to unstructured (unmarshal): %w
- failed to decode non-Table object
- empty object list provided
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/b4012ae431356fd9.
Report an issue: GitHub.