derailed/k9s · error

expecting a nuker for %q

Error message

expecting a nuker for %q

What it means

The Pod viewer's delete command (internal/view/pod.go:200) resolves the DAO for its GVR and type-asserts it to dao.Nuker (the interface providing Delete with propagation/grace). If the accessor registered for that GVR does not implement Delete, the assertion fails and the delete is aborted with this error.

Source

Thrown at internal/view/pod.go:200

	}

	return nil
}

func (p *Pod) killCmd(evt *tcell.EventKey) *tcell.EventKey {
	selections := p.GetTable().GetSelectedItems()
	if len(selections) == 0 {
		return evt
	}

	res, err := dao.AccessorFor(p.App().factory, p.GVR())
	if err != nil {
		p.App().Flash().Err(err)
		return nil
	}
	nuker, ok := res.(dao.Nuker)
	if !ok {
		p.App().Flash().Err(fmt.Errorf("expecting a nuker for %q", p.GVR()))
		return nil
	}
	if len(selections) > 1 {
		p.App().Flash().Infof("Delete %d marked %s", len(selections), p.GVR())
	} else {
		p.App().Flash().Infof("Delete resource %s %s", p.GVR(), selections[0])
	}
	p.GetTable().ShowDeleted()
	for _, path := range selections {
		if err := nuker.Delete(context.Background(), path, nil, dao.NowGrace); err != nil {
			p.App().Flash().Errf("Delete failed with %s", err)
		} else {
			p.App().factory.DeleteForwarder(path)
		}
		p.GetTable().DeleteMark(path)
	}
	p.Refresh()

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Delete via kubectl instead: 'kubectl delete <resource> <name> -n <ns>'
  2. If this is a custom DAO, implement dao.Nuker: Delete(ctx, path, propagation, grace) error
  3. Verify the DAO registered in the registry for the GVR is the intended one (dao.AccessorFor lookup)
  4. Check k9s is not in readonly mode / custom GVR aliasing is not misrouting the viewer

Example fix

// before
type MyDAO struct{ dao.Generic }
// ctrl-d -> expecting a nuker for "pods"

// after
type MyDAO struct{ dao.Generic }

func (d *MyDAO) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, grace dao.Grace) error {
  return d.Generic.Delete(ctx, path, propagation, grace)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// gate the delete action on the DAO capability at bind time
res, err := dao.AccessorFor(p.App().factory, p.GVR())
if err != nil { return }
if _, ok := res.(dao.Nuker); !ok {
    // do not bind ctrl-d for this viewer
    return
}

Type guard

func isNuker(res dao.Resource) bool {
    _, ok := res.(dao.Nuker)
    return ok
}

Try / catch

// comma-ok assert, never panic; surface a flash and abort the command
nuker, ok := res.(dao.Nuker)
if !ok {
    p.App().Flash().Err(fmt.Errorf("expecting a nuker for %q", p.GVR()))
    return nil
}

Prevention

When it happens

Trigger: Pressing ctrl-d on a resource whose DAO accessor is a generic implementation without Delete — typically a custom/aliased GVR routed to the pod viewer, or a fork where a DAO was replaced with one that no longer satisfies dao.Nuker.

Common situations: Custom resource viewers built on the pod browser; k9s upgrades where the dao.Nuker interface signature changed (e.g. grace period parameter added) breaking older custom DAOs; readonly-ish DAOs deliberately omitting Delete.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/f046153ed597c1e0. Report an issue: GitHub.