derailed/k9s · error

user is not authorized to restart %q

Error message

user is not authorized to restart %q

What it means

restartRes (internal/dao/dp.go:399-420) performs a rollout restart (patch with a restarted-at annotation) for generic workload types. After fetching the object it requires the patch verb on the workload's GVR in the namespace; denial returns this error printing the GVR (e.g. apps/v1:deployments).

Source

Thrown at internal/dao/dp.go:415

func restartRes[T runtime.Object](ctx context.Context, f Factory, gvr *client.GVR, path string, opts *metav1.PatchOptions) error {
	o, err := f.Get(gvr, path, true, labels.Everything())
	if err != nil {
		return err
	}
	var r = new(T)
	err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, r)
	if err != nil {
		return err
	}

	ns, n := client.Namespaced(path)
	auth, err := f.Client().CanI(ns, gvr, n, client.PatchAccess)
	if err != nil {
		return err
	}
	if !auth {
		return fmt.Errorf("user is not authorized to restart %q", gvr)
	}

	dial, err := f.Client().Dial()
	if err != nil {
		return err
	}

	before, err := runtime.Encode(scheme.Codecs.LegacyCodec(appsv1.SchemeGroupVersion), *r)
	if err != nil {
		return err
	}
	after, err := polymorphichelpers.ObjectRestarterFn(*r)
	if err != nil {
		return err
	}
	diff, err := strategicpatch.CreateTwoWayMergePatch(before, after, *r)
	if err != nil {
		return err

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Verify: kubectl auth can-i patch deployments -n <ns> (or daemonsets/statefulsets)
  2. Grant verbs: ["patch"] on the relevant apps resources in the Role
  3. Or restart out-of-band (kubectl rollout restart with a permitted identity)
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight patch permission for restart on the exact GVR.
func CanRestart(c client.Client, gvr *client.GVR, ns string) (bool, error) {
	return c.CanI(ns, gvr, "", client.PatchAccess)
}

Try / catch

if err := restartRes[*appsv1.Deployment](ctx, f, client.DpGVR, path, &opts); err != nil {
    if strings.Contains(err.Error(), "not authorized to restart") {
        return fmt.Errorf("RBAC: add verbs:[patch] on %s in namespace %s", gvr, ns)
    }
    return err
}

Prevention

When it happens

Trigger: Invoking k9s's restart action on a Deployment/DaemonSet/StatefulSet while the identity lacks `patch` on that resource type in the namespace. The object is fetched from cache first, so the resource exists - only authorization fails.

Common situations: Read-plus-update roles missing the patch verb; break-glass procedures where restart is reserved to SRE roles; contractors granted list/get/watch only.

Related errors


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