derailed/k9s · error

user is not authorized to update portforward

Error message

user is not authorized to update portforward

What it means

After confirming the pod is Running, Start separately authorizes create on the pods/portforward subresource — the same subresource kubectl port-forward uses. Plain pod permissions never imply this subresource, so it must be granted explicitly.

Source

Thrown at internal/dao/port_forwarder.go:149

	}

	podName := strings.Split(n, "|")[0]
	var res Pod
	res.Init(p, client.PodGVR)
	pod, err := res.GetInstance(client.FQN(ns, podName))
	if err != nil {
		return nil, err
	}
	if pod.Status.Phase != v1.PodRunning {
		return nil, fmt.Errorf("unable to forward port because pod is not running. Current status=%v", pod.Status.Phase)
	}

	auth, err = p.Client().CanI(ns, client.PodGVR.WithSubResource("portforward"), "", []string{client.CreateVerb})
	if err != nil {
		return nil, err
	}
	if !auth {
		return nil, fmt.Errorf("user is not authorized to update portforward")
	}

	cfg, err := p.Client().RestConfig()
	if err != nil {
		return nil, err
	}
	cfg.GroupVersion = &schema.GroupVersion{Group: "", Version: "v1"}
	cfg.APIPath = "/api"
	codec, _ := codec()
	cfg.NegotiatedSerializer = codec.WithoutConversion()
	clt, err := rest.RESTClientFor(cfg)
	if err != nil {
		return nil, err
	}
	req := clt.Post().
		Resource("pods").
		Namespace(ns).
		Name(podName).

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Grant create on the subresource: resources ["pods/portforward"] verbs ["create"]
  2. Verify: kubectl auth can-i create pods/portforward -n <ns>
  3. If policy forbids tunnels, use an alternative (Service/Ingress, kubectl debug, ephemeral containers)

Example fix

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: port-forwarder
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods", "pods/portforward"]
  verbs: ["get", "create"]
Defensive patterns

Strategy: validation

Validate before calling

ok, err := client.CanI(ns, client.PodGVR.WithSubResource("portforward"), "", []string{"create"})
if err != nil { return err }
if !ok { return fmt.Errorf("create on pods/portforward denied in %s", ns) }

Try / catch

if _, err := pf.Start(path, tunnel); err != nil {
    if strings.Contains(err.Error(), "not authorized to update portforward") {
        // add create pods/portforward to the role, then retry
    }
}

Prevention

When it happens

Trigger: CanI(ns, pods/portforward, "", create) false — the role covers pods but omits the portforward subresource.

Common situations: RBAC templates that copy pod rules without subresources; cluster policies that deliberately block tunnels (security baselines forbidding port-forward to production); users confused because kubectl get pods works fine.

Related errors


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