derailed/k9s · warning
strings.Join(errs, " - ")
Error message
strings.Join(errs, " - ")
What it means
CustomResourceDefinition.diagnose accumulates per-version findings — deprecation warnings (or the generic '<name>[<ver>] is deprecated' when a deprecated version omits a warning) and 'CRD <n> is no longer served by the api server' when no version has Served=true — then joins them with ' - ' into one error. It is the CRD list's health column: each condition is advisory, describing deprecation/serving state rather than a k9s failure.
Source
Thrown at internal/render/crd.go:132
ee = append(ee, fmt.Errorf("%s", *v.DeprecationWarning))
} else {
ee = append(ee, fmt.Errorf("%s[%s] is deprecated", n, v.Name))
}
}
}
if !served {
ee = append(ee, fmt.Errorf("CRD %s is no longer served by the api server", n))
}
if len(ee) == 0 {
return nil
}
errs := make([]string, 0, len(ee))
for _, e := range ee {
errs = append(errs, e.Error())
}
return errors.New(strings.Join(errs, " - "))
}
View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- For deprecation messages: migrate manifests/clients off the deprecated version (the message names CRD and version, or carries the upstream deprecationWarning text).
- For 'no longer served': set Served:true on the intended version in the CRD spec (kubectl edit crd <name>) or remove the dead CRD.
- Treat the row as a warning signal — no k9s-side remediation is expected.
Example fix
# before
versions:
- name: v1beta1
served: false
storage: true
# after
versions:
- name: v1
served: true
storage: true
- name: v1beta1
served: false
storage: false
deprecated: true
deprecationWarning: "use v1" Defensive patterns
Strategy: validation
Validate before calling
func crdHealthy(name string, vv []v1.CustomResourceDefinitionVersion) bool {
served := false
for _, v := range vv {
if v.Served { served = true }
if v.Deprecated { return false } // deprecation surfaces in diagnose
}
return served && len(vv) > 0
} Try / catch
if err := crdDiagnose(name, versions); err != nil {
msg := err.Error() // dash-joined: parse segments to act per finding (deprecation vs not served)
if strings.Contains(msg, "no longer served") { /* set Served:true or delete CRD */ }
} Prevention
- Set deprecationWarning on deprecated CRD versions so the message is actionable.
- During version migrations keep exactly one Served+Storage version and mark old ones deprecated.
- Migrate clients off deprecated versions when the warning appears.
When it happens
Trigger: Viewing CRDs where at least one spec.versions[] entry has Deprecated:true (with or without deprecationWarning), or where the versions list has no entry with Served:true; multiple findings concatenate into a single dash-joined message.
Common situations: Operators deprecating v1beta1-style storage versions during upgrades; admins flipping Served:false during version migrations; CRDs installed with all versions unserved by mistake.
Related errors
- failed benchmark
- container is not ready
- expecting cronjob resource
- expecting Deployment resource
- expecting ServiceAccount resource
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/ec148d5c4416ccc8.
Report an issue: GitHub.