derailed/k9s · error
expecting StatefulSet resource
Error message
expecting StatefulSet resource
What it means
DaemonSet.Scan converts every DaemonSet in a namespace into appsv1.DaemonSet to find ConfigMap, Secret and PVC references (internal/dao/ds.go:178). The message is misleading: the code converts appsv1.DaemonSet but the sentinel says 'expecting StatefulSet resource' — a copy-paste from the StatefulSet scanner. Functionally it still means FromUnstructured could not fit a cached daemonsets.apps object into the compiled struct, and one bad object aborts the whole scan.
Source
Thrown at internal/dao/ds.go:178
}
return refs, nil
}
// Scan scans for cluster refs.
func (d *DaemonSet) Scan(_ context.Context, gvr *client.GVR, fqn string, wait bool) (Refs, error) {
ns, n := client.Namespaced(fqn)
oo, err := d.getFactory().List(d.gvr, ns, wait, labels.Everything())
if err != nil {
return nil, err
}
refs := make(Refs, 0, len(oo))
for _, o := range oo {
var ds appsv1.DaemonSet
err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &ds)
if err != nil {
return nil, errors.New("expecting StatefulSet resource")
}
switch gvr {
case client.CmGVR:
if !hasConfigMap(&ds.Spec.Template.Spec, n) {
continue
}
refs = append(refs, Ref{
GVR: d.GVR(),
FQN: client.FQN(ds.Namespace, ds.Name),
})
case client.SecGVR:
found, err := hasSecret(d.Factory, &ds.Spec.Template.Spec, ds.Namespace, n, wait)
if err != nil {
slog.Warn("Unable to locate secret",
slogs.FQN, fqn,
slogs.Error, err,
)
continueView on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Do not search StatefulSets — the message is wrong; inspect kubectl get daemonsets.apps -n <ns> -o yaml for mistyped fields.
- Upgrade k9s (newer builds may fix the message and keep conversion schemas current).
- Fix the message locally or upstream: change ds.go:178 to 'expecting DaemonSet resource'.
- Wrap the converter error with %w to expose the offending field.
- Patch the loop to skip unparsable objects with a warning instead of aborting the scan.
Example fix
// before (ds.go:178 — message copy-pasted from sts.go)
return nil, errors.New("expecting StatefulSet resource")
// after
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &ds); err != nil {
slog.Warn("skip unparsable daemonset", "fqn", client.FQN(u.GetNamespace(), u.GetName()), "err", err)
continue
} Defensive patterns
Strategy: try-catch
Validate before calling
for _, o := range oo {
u, ok := o.(*unstructured.Unstructured)
if !ok || u.GroupVersionKind().Kind != "DaemonSet" {
continue
}
// safe to convert below
} Type guard
func isDaemonSet(o runtime.Object) bool {
u, ok := o.(*unstructured.Unstructured)
return ok && u.GroupVersionKind().Kind == "DaemonSet" && u.GroupVersionKind().Group == "apps"
} Try / catch
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &ds); err != nil {
slog.Warn("skip unparsable daemonset", "fqn", fqn, "err", err)
continue // the stock message wrongly says StatefulSet; guard daemonsets
} Prevention
- Do not trust resource names in error strings — verify the code path that prints them.
- Make scans degrade per object with logging.
- When patching k9s locally, fix the ds.go:178 message to say DaemonSet to save future debugging.
- Align k9s and cluster versions to avoid conversion failures at the source.
When it happens
Trigger: Opening an xray or reference scan (CmGVR, SecGVR, PvcGVR) in a namespace where a stored DaemonSet fails conversion to the compiled appsv1.DaemonSet struct — version skew, GVR shadowing, or webhook-written out-of-schema fields. When debugging, ignore the StatefulSet wording and inspect daemonsets.
Common situations: Developers chasing a phantom StatefulSet problem because the message names the wrong kind; xray views failing after cluster upgrades on older k9s builds; DaemonSets mutated by legacy tooling.
Related errors
- expecting DaemonSet resource
- expecting Deployment resource
- expecting cronjob resource
- expecting Deployment resource
- expecting ServiceAccount resource
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/382b5427173af178.
Report an issue: GitHub.