derailed/k9s · error
unable to marshal resource %w
Error message
unable to marshal resource %w
What it means
Generic.ToYAML (internal/dao/generic.go:92-106) fetches a resource and serializes it (dao.ToYAML) for the YAML view. If serialization of the fetched object fails, this error wraps the marshal error (note: the format string omits a colon, so the message reads "unable to marshal resource <err>").
Source
Thrown at internal/dao/generic.go:104
return dial.Namespace(ns).Get(ctx, n, opts)
}
// Describe describes a resource.
func (g *Generic) Describe(path string) (string, error) {
return Describe(g.Client(), g.gvr, path)
}
// ToYAML returns a resource yaml.
func (g *Generic) ToYAML(path string, showManaged bool) (string, error) {
o, err := g.Get(context.Background(), path)
if err != nil {
return "", err
}
raw, err := ToYAML(o, showManaged)
if err != nil {
return "", fmt.Errorf("unable to marshal resource %w", err)
}
return raw, nil
}
// Delete deletes a resource.
func (g *Generic) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, grace Grace) error {
ns, n := client.Namespaced(path)
auth, err := g.Client().CanI(ns, g.gvr, n, []string{client.DeleteVerb})
if err != nil {
return err
}
if !auth {
return fmt.Errorf("user is not authorized to delete %s", path)
}
var gracePeriod *int64
if grace != DefaultGrace {
gracePeriod = (*int64)(&grace)View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Retry the view with managed fields hidden (toggle y) - stripping managedFields sometimes removes the offending payload
- Inspect the resource with kubectl get <res> <name> -o yaml to spot NaN/Infinity values
- Report/fix the operator writing non-finite numbers; represent them as strings ("Infinity") as Prometheus configs do
- As a last resort read the object via kubectl, since kubectl's JSON-path output tolerates these values
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-scan an unstructured object for values yaml cannot encode (NaN/Inf).
func YamlSafe(u *unstructured.Unstructured) error {
var walk func(v any) error
walk = func(v any) error {
switch t := v.(type) {
case float64:
if math.IsNaN(t) || math.IsInf(t, 0) { return fmt.Errorf("non-finite number %v in %s", t, u.GetName()) }
case map[string]any:
for _, x := range t { if err := walk(x); err != nil { return err } }
case []any:
for _, x := range t { if err := walk(x); err != nil { return err } }
}
return nil
}
return walk(u.Object)
} Try / catch
raw, err := g.ToYAML(path, showManaged)
if err != nil && strings.Contains(err.Error(), "unable to marshal resource") {
// degrade gracefully: dump JSON instead, which tolerates these values
raw, err = json.MarshalIndent(o.Object, "", " ")
}
if err != nil { return "", err } Prevention
- Store thresholds as strings ("Infinity"), never bare .inf/NaN in CRDs
- Wrap the YAML view in a JSON fallback so one bad field does not break viewing
- Toggle managed-fields off first; it removes payload that sometimes carries the bad value
When it happens
Trigger: The unstructured object contains values go-yaml cannot encode: NaN/+Inf/-Inf float values (common in metrics CRDs like ServiceMonitor or PrometheusRule objects and status fields), unsupported map key types, or huge/malformed annotations - data that survived JSON decoding but fails YAML marshaling.
Common situations: Viewing YAML of monitoring CRDs whose threshold fields legitimately hold Infinity; resources with exotic annotation payloads written by operators; k9s showManaged toggling which strips/keeps managed fields during marshal.
Related errors
- default value %q for number input %q is not a valid number
- plugin validation failed for %s: %w
- plugin unmarshal failed for %s: %w
- plugin %q validation failed for %s: %w
- no benchmark dir found in context
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/a26695e516fa3939.
Report an issue: GitHub.