derailed/k9s · error
expecting a sanitizer for %q
Error message
expecting a sanitizer for %q
What it means
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.
Source
Thrown at internal/view/pod.go:266
return nil
}
if err := containerAttachIn(p.App(), p, path, ""); err != nil {
p.App().Flash().Err(err)
}
return nil
}
func (p *Pod) sanitizeCmd(*tcell.EventKey) *tcell.EventKey {
res, err := dao.AccessorFor(p.App().factory, p.GVR())
if err != nil {
p.App().Flash().Err(err)
return nil
}
s, ok := res.(dao.Sanitizer)
if !ok {
p.App().Flash().Err(fmt.Errorf("expecting a sanitizer for %q", p.GVR()))
return nil
}
msg := fmt.Sprintf("Sanitize deletes all pods in completed/error state\nPlease enter [orange::b]%s[-::-] to proceed.", magicPrompt)
dialog.ShowConfirmAck(p.App().App, p.App().Content.Pages, magicPrompt, true, "Sanitize", msg, func() {
ctx, cancel := context.WithTimeout(context.Background(), 5*p.App().Conn().Config().CallTimeout())
defer cancel()
total, err := s.Sanitize(ctx, p.GetTable().GetModel().GetNamespace())
if err != nil {
p.App().Flash().Err(err)
return
}
p.App().Flash().Infof("Sanitized %d %s", total, p.GVR())
p.Refresh()
}, func() {})
return nil
}View on GitHub (pinned to 2d3ccc6ba2)
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
Example fix
// before: sanitize bound on non-pod viewer
// -> expecting a sanitizer for "mygvr"
// after: keep sanitize on the pod DAO only
func (d *PodDAO) Sanitize(ctx context.Context, ns string) (int, error) {
// delete pods in Succeeded/Failed phase, return count
} Defensive patterns
Strategy: type-guard
Validate before calling
// only offer sanitize when the accessor implements dao.Sanitizer
if _, ok := res.(dao.Sanitizer); !ok {
p.App().Flash().Err(fmt.Errorf("%s does not support sanitize", p.GVR()))
return nil
} Type guard
func isSanitizer(res dao.Resource) bool {
_, ok := res.(dao.Sanitizer)
return ok
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- expecting a switchable resource
- expecting a switchable resource
- resource is not restartable
- expecting a job runner resource for %q
- expecting a ContainsPodSpec for %q but got %T
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/c1bf740cad3721f7.
Report an issue: GitHub.