derailed/k9s · error

expecting a switchable resource

Error message

expecting a switchable resource

What it means

Returned by the context-switch path in `Command.execCmd` (internal/view/command.go:~202). It fetches the DAO for `client.CtGVR` (contexts resource) via `dao.AccessorFor` and type-asserts it to `dao.Switchable`. In stock k9s the registered contexts DAO always implements Switchable (it calls the config switch API), so this error is an internal invariant failure: the factory returned an accessor that cannot switch contexts.

Source

Thrown at internal/view/command.go:202

	if comd != nil {
		p.Merge(comd)
	}

	if context, ok := p.HasContext(); ok {
		if context != c.app.Config.ActiveContextName() {
			if err := c.app.Config.Save(true); err != nil {
				slog.Error("Config save failed during command exec", slogs.Error, err)
			} else {
				slog.Debug("Successfully saved config", slogs.Context, context)
			}
		}
		res, err := dao.AccessorFor(c.app.factory, client.CtGVR)
		if err != nil {
			return err
		}
		switcher, ok := res.(dao.Switchable)
		if !ok {
			return errors.New("expecting a switchable resource")
		}
		if err := switcher.Switch(context); err != nil {
			slog.Error("Unable to switch context", slogs.Error, err)
			return err
		}
		if err := c.app.switchContext(p, false); err != nil {
			return err
		}
	}

	ns := c.app.Config.ActiveNamespace()
	if cns, ok := p.NSArg(); ok {
		ns = cns
	}
	if ok, err := dao.MetaAccess.IsNamespaced(gvr); ok && err == nil {
		if err := c.app.switchNS(ns); err != nil {
			return err
		}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Restore the stock contexts DAO registration for client.CtGVR in the factory (it must implement dao.Switchable)
  2. On a fork, make your custom contexts accessor implement the Switchable interface (Switch(name) error)
  3. Verify you are not running a test/stub factory in production; check factory init order
Defensive patterns

Strategy: type-guard

Type guard

func canSwitch(f dao.Factory, gvr *client.GVR) bool {
    a, err := dao.AccessorFor(f, gvr)
    _, ok := a.(dao.Switchable)
    return err == nil && ok
}

Try / catch

if _, ok := res.(dao.Switchable); !ok {
    return fmt.Errorf("expecting a switchable resource for %s", gvr)
}

Prevention

When it happens

Trigger: `dao.AccessorFor(factory, client.CtGVR)` succeeds but the returned accessor does not implement `dao.Switchable` — only possible when factory registration is customized (custom builds, forks, test factories registering a plain DAO for contexts) or the DAO type changed in a fork.

Common situations: Forked k9s builds or plugins that override DAO registration for the contexts GVR; unit tests with a mock factory returning a generic accessor; version drift after rebasing a fork on upstream where the contexts DAO interface moved.

Related errors


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