{"record":{"id":"c1bf740cad3721f7","repo":"derailed/k9s","slug":"expecting-a-sanitizer-for-q","errorCode":null,"errorMessage":"expecting a sanitizer for %q","messagePattern":"expecting a sanitizer for %q","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/view/pod.go","lineNumber":266,"sourceCode":"\t\treturn nil\n\t}\n\n\tif err := containerAttachIn(p.App(), p, path, \"\"); err != nil {\n\t\tp.App().Flash().Err(err)\n\t}\n\n\treturn nil\n}\n\nfunc (p *Pod) sanitizeCmd(*tcell.EventKey) *tcell.EventKey {\n\tres, err := dao.AccessorFor(p.App().factory, p.GVR())\n\tif err != nil {\n\t\tp.App().Flash().Err(err)\n\t\treturn nil\n\t}\n\ts, ok := res.(dao.Sanitizer)\n\tif !ok {\n\t\tp.App().Flash().Err(fmt.Errorf(\"expecting a sanitizer for %q\", p.GVR()))\n\t\treturn nil\n\t}\n\n\tmsg := fmt.Sprintf(\"Sanitize deletes all pods in completed/error state\\nPlease enter [orange::b]%s[-::-] to proceed.\", magicPrompt)\n\tdialog.ShowConfirmAck(p.App().App, p.App().Content.Pages, magicPrompt, true, \"Sanitize\", msg, func() {\n\t\tctx, cancel := context.WithTimeout(context.Background(), 5*p.App().Conn().Config().CallTimeout())\n\t\tdefer cancel()\n\t\ttotal, err := s.Sanitize(ctx, p.GetTable().GetModel().GetNamespace())\n\t\tif err != nil {\n\t\t\tp.App().Flash().Err(err)\n\t\t\treturn\n\t\t}\n\t\tp.App().Flash().Infof(\"Sanitized %d %s\", total, p.GVR())\n\t\tp.Refresh()\n\t}, func() {})\n\n\treturn nil\n}","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/view/pod.go#L248-L284","documentation":"sanitizeCmd (internal/view/pod.go:266) asserts that the DAO for the viewer's GVR implements dao.Sanitizer (interface with Sanitize(ctx, ns)). Only the pod DAO implements it; any other accessor, or a customized pod DAO that drops the method, fails the assertion before the confirmation dialog is shown.","triggerScenarios":"Pressing the sanitize keybinding on a viewer whose GVR's accessor lacks Sanitize — e.g. the keybinding was rebound/copied to another resource's browser, or a fork replaced the pod DAO.","commonSituations":"Custom keybinding maps that spread 'Sanitize' beyond the pod view; k9s forks with modified DAO registries; interface drift after upgrading k9s where Sanitize's signature changed.","solutions":["Run Sanitize from the real pods view (':po') where the pod DAO backs it","Clean up completed/failed pods manually: 'kubectl delete pods -n <ns> --field-selector=status.phase=Succeeded,Failed'","If custom DAO: implement dao.Sanitizer — Sanitize(ctx context.Context, ns string) (int, error)","Remove the sanitize binding from viewers whose resources are not pods"],"exampleFix":"// before: sanitize bound on non-pod viewer\n// -> expecting a sanitizer for \"mygvr\"\n\n// after: keep sanitize on the pod DAO only\nfunc (d *PodDAO) Sanitize(ctx context.Context, ns string) (int, error) {\n  // delete pods in Succeeded/Failed phase, return count\n}","handlingStrategy":"type-guard","validationCode":"// only offer sanitize when the accessor implements dao.Sanitizer\nif _, ok := res.(dao.Sanitizer); !ok {\n    p.App().Flash().Err(fmt.Errorf(\"%s does not support sanitize\", p.GVR()))\n    return nil\n}","typeGuard":"func isSanitizer(res dao.Resource) bool {\n    _, ok := res.(dao.Sanitizer)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Keep the sanitize binding scoped to the pods viewer only","Compile-time assert in DAOs: var _ dao.Sanitizer = (*Pod)(nil)","Provide a kubectl fallback habit: kubectl delete pods --field-selector=status.phase=Succeeded"],"tags":["k9s","sanitize","dao","type-assertion","pods"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}