{"record":{"id":"07b55968e14992c8","repo":"derailed/k9s","slug":"user-is-not-authorized-to-restart-q","errorCode":null,"errorMessage":"user is not authorized to restart %q","messagePattern":"user is not authorized to restart %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/dp.go","lineNumber":415,"sourceCode":"\nfunc restartRes[T runtime.Object](ctx context.Context, f Factory, gvr *client.GVR, path string, opts *metav1.PatchOptions) error {\n\to, err := f.Get(gvr, path, true, labels.Everything())\n\tif err != nil {\n\t\treturn err\n\t}\n\tvar r = new(T)\n\terr = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, r)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tns, n := client.Namespaced(path)\n\tauth, err := f.Client().CanI(ns, gvr, n, client.PatchAccess)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !auth {\n\t\treturn fmt.Errorf(\"user is not authorized to restart %q\", gvr)\n\t}\n\n\tdial, err := f.Client().Dial()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tbefore, err := runtime.Encode(scheme.Codecs.LegacyCodec(appsv1.SchemeGroupVersion), *r)\n\tif err != nil {\n\t\treturn err\n\t}\n\tafter, err := polymorphichelpers.ObjectRestarterFn(*r)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdiff, err := strategicpatch.CreateTwoWayMergePatch(before, after, *r)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/dp.go#L397-L433","documentation":"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).","triggerScenarios":"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.","commonSituations":"Read-plus-update roles missing the patch verb; break-glass procedures where restart is reserved to SRE roles; contractors granted list/get/watch only.","solutions":["Verify: kubectl auth can-i patch deployments -n <ns> (or daemonsets/statefulsets)","Grant verbs: [\"patch\"] on the relevant apps resources in the Role","Or restart out-of-band (kubectl rollout restart with a permitted identity)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight patch permission for restart on the exact GVR.\nfunc CanRestart(c client.Client, gvr *client.GVR, ns string) (bool, error) {\n\treturn c.CanI(ns, gvr, \"\", client.PatchAccess)\n}","typeGuard":null,"tryCatchPattern":"if err := restartRes[*appsv1.Deployment](ctx, f, client.DpGVR, path, &opts); err != nil {\n    if strings.Contains(err.Error(), \"not authorized to restart\") {\n        return fmt.Errorf(\"RBAC: add verbs:[patch] on %s in namespace %s\", gvr, ns)\n    }\n    return err\n}","preventionTips":["Grant patch on deployments/daemonsets/statefulsets to roles expected to do rollout restarts","Gate the restart keybinding in shared k9s skins for read-only identities"],"tags":["go","kubernetes","rbac","k9s","restart","rollout","authorization"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}