derailed/k9s · error

expecting a controller resource for %q

Error message

expecting a controller resource for %q

What it means

internal/view/pf_extender.go's fetchPodName resolves the DAO for the viewer's GVR via dao.AccessorFor and type-asserts it to the dao.Controller interface (which provides Pod(path) to find the owning/controlled pod). If the registered accessor does not implement dao.Controller, the assertion fails and this error is returned with the GVR string. It signals that the port-forward extender was attached to a resource whose data-access object cannot map a resource path to a pod.

Source

Thrown at internal/view/pf_extender.go:102

	}

	pf := NewPortForward(client.PfGVR)
	pf.SetContextFn(p.portForwardContext)
	if err := p.App().inject(pf, false); err != nil {
		p.App().Flash().Err(err)
	}

	return nil
}

func (p *PortForwardExtender) fetchPodName(path string) (string, error) {
	res, err := dao.AccessorFor(p.App().factory, p.GVR())
	if err != nil {
		return "", err
	}
	ctrl, ok := res.(dao.Controller)
	if !ok {
		return "", fmt.Errorf("expecting a controller resource for %q", p.GVR())
	}

	return ctrl.Pod(path)
}

func (p *PortForwardExtender) portForwardContext(ctx context.Context) context.Context {
	if bc := p.App().BenchFile; bc != "" {
		ctx = context.WithValue(ctx, internal.KeyBenchCfg, p.App().BenchFile)
	}

	return context.WithValue(ctx, internal.KeyPath, p.GetTable().GetSelectedItem())
}

// ----------------------------------------------------------------------------
// Helpers...

func ensurePodPortFwdAllowed(factory dao.Factory, podName string) error {
	pod, err := fetchPod(factory, podName)

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Port-forward from a viewer whose DAO implements dao.Controller (deployments, statefulsets, daemonsets, jobs, pods) instead of the failing GVR
  2. If this is your custom resource, implement the dao.Controller interface (Pod(path) method) on its DAO so the extender can resolve the backing pod
  3. Register the correct DAO in the dao registry (dao.AccessorFor must return a controller-capable accessor for that GVR)
  4. As a fallback, find the pod behind the resource manually (kubectl get pods --show-labels) and port-forward from the pod view

Example fix

// before: extender attached to a GVR whose DAO is generic
res, _ := dao.AccessorFor(p.App().factory, p.GVR())
ctrl, ok := res.(dao.Controller)
// ok == false -> error

// after: implement dao.Controller on the custom DAO
type MyCRD struct {
  dao.Generic
}

func (d *MyCRD) Pod(path string) (string, error) {
  // resolve owner -> pod name
  return ownerPod(d.Factory(), path)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before calling fetchPodName, verify the accessor is controller-capable
res, err := dao.AccessorFor(f, gvr)
if err != nil { return err }
if _, ok := res.(dao.Controller); !ok {
    return fmt.Errorf("resource %s cannot resolve a pod; port-forward from a controller or pod view", gvr)

Type guard

func asController(res dao.Resource) (dao.Controller, bool) {
    c, ok := res.(dao.Controller)
    return c, ok
}

// usage
if ctrl, ok := asController(res); ok {
    pod, err := ctrl.Pod(path)
}

Try / catch

// Go: check the comma-ok assertion instead of panicking; degrade gracefully
if ctrl, ok := res.(dao.Controller); ok {
    if podName, err := ctrl.Pod(path); err == nil {
        return startForward(v, podName, pts)
    }
} else {
    log.Debug("accessor lacks Controller", "gvr", gvr)
}

Prevention

When it happens

Trigger: Invoking the port-forward command (shift+f) from a viewer whose GVR's DAO is a generic/non-controller implementation — e.g. a custom resource added via k9s plugins/aliases whose accessor is dao.Generic, or any GVR registered in the DAO registry without a Pod(path) method.

Common situations: Extending k9s with custom CRD viewers and reusing PortForwardExtender on them; a k9s version bump where the dao.Controller interface gained methods a fork's custom DAO no longer satisfies; wiring the extender to a GVR that is not a pod controller (Deployment-like) by mistake.

Related errors


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