derailed/k9s · error
expecting Deployment resource
Error message
expecting Deployment resource
What it means
k9s's Deployment DAO fetches a single Deployment from the shared informer cache as *unstructured.Unstructured and converts it into appsv1.Deployment via runtime.DefaultUnstructuredConverter.FromUnstructured (internal/dao/dp.go:96). The sentinel 'expecting Deployment resource' is returned when conversion fails; the underlying converter error is dropped, so the real offending field is invisible. It means the cached object under deployments.apps does not fit the k8s.io/api schema k9s was compiled against.
Source
Thrown at internal/dao/dp.go:96
dp, err := d.GetInstance(fqn)
if err != nil {
return "", err
}
return podFromSelector(d.Factory, dp.Namespace, dp.Spec.Selector.MatchLabels)
}
// GetInstance fetch a matching deployment.
func (d *Deployment) GetInstance(fqn string) (*appsv1.Deployment, error) {
o, err := d.Factory.Get(d.gvr, fqn, true, labels.Everything())
if err != nil {
return nil, err
}
var dp appsv1.Deployment
err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &dp)
if err != nil {
return nil, errors.New("expecting Deployment resource")
}
return &dp, nil
}
// ScanSA scans for serviceaccount refs.
func (d *Deployment) ScanSA(_ context.Context, 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 dp appsv1.Deployment
err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &dp)
if err != nil {View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Inspect the object: kubectl get deployment.apps <name> -n <ns> -o yaml and look for unexpected or mistyped fields; fix via kubectl edit.
- Upgrade k9s so its vendored k8s.io/* versions match the cluster minor version.
- Confirm deployments.apps is served by the core apiserver and not shadowed (kubectl api-resources --api-group=apps).
- Restart k9s to rebuild informer caches after cluster or webhook changes.
- If embedding, wrap the converter error with %w to reveal the offending field.
Example fix
// before
err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &dp)
if err != nil {
return nil, errors.New("expecting Deployment resource")
}
// after
u, ok := o.(*unstructured.Unstructured)
if !ok {
return nil, fmt.Errorf("expected unstructured deployment, got %T", o)
}
var dp appsv1.Deployment
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &dp); err != nil {
return nil, fmt.Errorf("deployment %q does not match v1 schema: %w", fqn, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
o, err := factory.Get(client.DpGVR, fqn, true, labels.Everything())
if err != nil { return err }
u, ok := o.(*unstructured.Unstructured)
if !ok || u.GroupVersionKind().Kind != "Deployment" {
return fmt.Errorf("not a deployment: %s", u.GroupVersionKind())
} Type guard
func isDeployment(o runtime.Object) bool {
u, ok := o.(*unstructured.Unstructured)
return ok && u.GroupVersionKind().Kind == "Deployment" && u.GroupVersionKind().Group == "apps"
} Try / catch
var dp appsv1.Deployment
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &dp); err != nil {
return nil, fmt.Errorf("deployment %q conversion: %w", fqn, err)
} Prevention
- Keep k9s's k8s.io/* dependencies aligned with the cluster minor version.
- Avoid kubectl patch --type=merge with values whose types differ from the schema.
- Assert *unstructured.Unstructured and check the GVK before converting in custom code.
- Restart k9s after cluster upgrades to refresh informer caches.
When it happens
Trigger: Calling dao.Deployment.GetInstance(fqn) — the deployment detail view, restart, scale or image actions — when the stored object has a field whose JSON type cannot be assigned to the compiled appsv1.Deployment struct: apiserver version skew, an aggregated API or CRD shadowing deployments.apps, or webhook-patched out-of-schema values.
Common situations: Old k9s builds against new clusters (or the reverse) where deployment spec/status fields changed shape; custom mutating webhooks writing extra fields; GitOps tools force-applying legacy manifests; embedding the DAO layer with a custom factory whose cache holds converted objects.
Related errors
- expecting cronjob resource
- expecting DaemonSet resource
- expecting Job resource
- expecting ServiceAccount resource
- expecting StatefulSet resource
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/ce780a4b4b3bdfe4.
Report an issue: GitHub.