{"record":{"id":"0c73349becca955d","repo":"derailed/k9s","slug":"expecting-deployment-resource-0c7334","errorCode":null,"errorMessage":"expecting Deployment resource","messagePattern":"expecting Deployment resource","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/pod.go","lineNumber":271,"sourceCode":"\t}\n\n\treturn outs, nil\n}\n\n// ScanSA scans for ServiceAccount refs.\nfunc (p *Pod) ScanSA(_ context.Context, fqn string, wait bool) (Refs, error) {\n\tns, n := client.Namespaced(fqn)\n\too, err := p.getFactory().List(p.gvr, ns, wait, labels.Everything())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trefs := make(Refs, 0, len(oo))\n\tfor _, o := range oo {\n\t\tvar pod v1.Pod\n\t\terr = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &pod)\n\t\tif err != nil {\n\t\t\treturn nil, errors.New(\"expecting Deployment resource\")\n\t\t}\n\t\t// Just pick controller less pods...\n\t\tif len(pod.OwnerReferences) > 0 {\n\t\t\tcontinue\n\t\t}\n\t\tif serviceAccountMatches(pod.Spec.ServiceAccountName, n) {\n\t\t\trefs = append(refs, Ref{\n\t\t\t\tGVR: p.GVR(),\n\t\t\t\tFQN: client.FQN(pod.Namespace, pod.Name),\n\t\t\t})\n\t\t}\n\t}\n\n\treturn refs, nil\n}\n\n// Scan scans for cluster resource refs.\nfunc (p *Pod) Scan(_ context.Context, gvr *client.GVR, fqn string, wait bool) (Refs, error) {","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/pod.go#L253-L289","documentation":"Pod.ScanSA lists pods in a namespace and converts each object into v1.Pod to match spec.serviceAccountName (only controller-less pods are considered) for the UsedBy action on ServiceAccounts (internal/dao/pod.go:271). The message is misleading: the conversion target is v1.Pod but the sentinel says 'expecting Deployment resource' — a copy-paste from dp.go. Functionally it still means one cached pod object could not be converted, and it aborts the whole scan.","triggerScenarios":"Running UsedBy on a ServiceAccount in a namespace where at least one stored Pod fails conversion to the compiled v1.Pod struct — k9s/cluster version skew (e.g. pod spec fields evolving across releases), an unusual apiserver, or sidecar-injected objects with out-of-schema fields. When debugging, ignore the Deployment wording and inspect pods.","commonSituations":"Developers inspecting deployments because the message names the wrong kind; reference scans failing after cluster upgrades on older k9s builds; meshes or injectors writing extra pod fields.","solutions":["Do not chase Deployments — the message is wrong; audit kubectl get pods -n <ns> -o yaml for mistyped or unexpected fields.","Upgrade k9s (newer builds match newer pod schemas and may fix the message).","Fix the message locally or upstream: change pod.go:271 to 'expecting Pod resource'.","Wrap the converter error with %w to expose the offending field.","Patch the loop to skip unparsable pods with a warning instead of aborting the scan."],"exampleFix":"// before (pod.go:271 — message copy-pasted from dp.go)\nreturn nil, errors.New(\"expecting Deployment resource\")\n// after\nif err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &pod); err != nil {\n    slog.Warn(\"skip unparsable pod\", \"fqn\", client.FQN(u.GetNamespace(), u.GetName()), \"err\", err)\n    continue\n}","handlingStrategy":"try-catch","validationCode":"for _, o := range oo {\n    u, ok := o.(*unstructured.Unstructured)\n    if !ok || u.GroupVersionKind().Kind != \"Pod\" {\n        continue\n    }\n    // safe to convert below\n}","typeGuard":"func isPod(o runtime.Object) bool {\n    u, ok := o.(*unstructured.Unstructured)\n    return ok && u.GroupVersionKind().Kind == \"Pod\" && u.GroupVersionKind().Group == \"\"\n}","tryCatchPattern":"if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &pod); err != nil {\n    slog.Warn(\"skip unparsable pod\", \"fqn\", fqn, \"err\", err)\n    continue // the stock message wrongly says Deployment; guard pods\n}","preventionTips":["Do not trust the resource name in the error string — confirm the failing code path.","Make scans skip-and-log per object so UsedBy survives one bad pod.","Keep injector webhooks schema-conformant; audit with kubectl get pods -o yaml.","Align k9s builds with cluster versions."],"tags":["kubernetes","go","type-conversion","pod","error-message-bug"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}