derailed/k9s · error

user is not authorized to patch a deployment

Error message

user is not authorized to patch a deployment

What it means

Deployment.SetImages (internal/dao/dp.go:205-217) applies a JSON patch to a Deployment's pod template to swap container images. It first requires the patch verb on deployments.apps in the namespace (client.PatchAccess via CanI); denial returns this error before building the patch.

Source

Thrown at internal/dao/dp.go:208

// GetPodSpec returns a pod spec given a resource.
func (d *Deployment) GetPodSpec(path string) (*v1.PodSpec, error) {
	dp, err := d.GetInstance(path)
	if err != nil {
		return nil, err
	}
	podSpec := dp.Spec.Template.Spec
	return &podSpec, nil
}

// SetImages sets container images.
func (d *Deployment) SetImages(ctx context.Context, path string, imageSpecs ImageSpecs) error {
	ns, n := client.Namespaced(path)
	auth, err := d.Client().CanI(ns, d.gvr, n, client.PatchAccess)
	if err != nil {
		return err
	}
	if !auth {
		return fmt.Errorf("user is not authorized to patch a deployment")
	}
	jsonPatch, err := GetTemplateJsonPatch(imageSpecs)
	if err != nil {
		return err
	}
	dial, err := d.Client().Dial()
	if err != nil {
		return err
	}
	_, err = dial.AppsV1().Deployments(ns).Patch(
		ctx,
		n,
		types.StrategicMergePatchType,
		jsonPatch,
		metav1.PatchOptions{},
	)
	return err
}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Verify: kubectl auth can-i patch deployments -n <ns>
  2. Add verbs: ["patch"] for deployments.apps in the Role, or use update-capable workflows the role already has
  3. Prefer the GitOps pipeline for image changes if mutation is intentionally locked down
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight patch permission for the set-image action.
func CanSetImage(c client.Client, ns string) (bool, error) {
	return c.CanI(ns, client.DpGVR, "", client.PatchAccess)
}

Try / catch

if err := d.SetImages(ctx, path, specs); err != nil {
    if strings.Contains(err.Error(), "not authorized to patch a deployment") {
        return fmt.Errorf("RBAC: add verbs:[patch] on deployments.apps in namespace %s", ns)
    }
    return err
}

Prevention

When it happens

Trigger: Using k9s's set-image action on a Deployment while the current identity lacks `patch deployments` in that namespace. Only the patch verb is checked; having update alone will still fail this pre-check.

Common situations: Developer roles granted update but not patch; GitOps-managed clusters where mutation via kubectl/k9s is intentionally blocked; wrong context selected in k9s.

Related errors


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