{"record":{"id":"6ee32a7e3e8f1ca2","repo":"derailed/k9s","slug":"current-user-can-t-edit-resource-s","errorCode":null,"errorMessage":"current user can't edit resource %s","messagePattern":"current user can't edit resource (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/view/browser.go","lineNumber":567,"sourceCode":"\t\tb.App().Flash().Err(err)\n\t}\n\n\treturn nil\n}\n\nfunc editRes(app *App, gvr *client.GVR, path string) error {\n\tif path == \"\" {\n\t\treturn fmt.Errorf(\"nothing selected %q\", path)\n\t}\n\tns, n := client.Namespaced(path)\n\tif n == \"\" {\n\t\treturn fmt.Errorf(\"missing resource name in path %q\", path)\n\t}\n\tif client.IsClusterScoped(ns) {\n\t\tns = client.BlankNamespace\n\t}\n\tif ok, err := app.Conn().CanI(ns, gvr, n, client.PatchAccess); !ok || err != nil {\n\t\treturn fmt.Errorf(\"current user can't edit resource %s\", gvr)\n\t}\n\n\targs := make([]string, 0, 10)\n\targs = append(args, \"edit\", gvr.FQN(n))\n\tif ns != client.BlankNamespace {\n\t\targs = append(args, \"-n\", ns)\n\t}\n\tif err := runK(app, &shellOpts{clear: true, args: args}); err != nil {\n\t\tapp.Flash().Errf(\"Edit command failed: %s\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (b *Browser) switchNamespaceCmd(evt *tcell.EventKey) *tcell.EventKey {\n\ti, err := strconv.Atoi(string(evt.Rune()))\n\tif err != nil {\n\t\tslog.Error(\"Unable to convert keystroke\", slogs.Error, err)","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/view/browser.go#L549-L585","documentation":"Before shelling out to kubectl edit, the app verifies RBAC with CanI(ns, gvr, name, PatchAccess); it returned either not-allowed or an error. kubectl edit patches the resource, so the user needs patch (and typically get) permission on that specific object. Note the underlying err is discarded — the same message appears for genuine denial and for an API failure inside CanI.","triggerScenarios":"User presses `e` on a resource they can view but not patch: Role/RoleBinding lacking verbs [\"patch\"], or a Role that grants patch cluster-wide but a tighter RoleRef on the specific object; also when CanI itself errored (API unreachable, SelfSubjectAccessReview broken by admission/OPA).","commonSituations":"Read-only cluster roles for support/observability teams; dev namespaces with restrictive RBAC; kyverno/OPA mutating or denying SelfSubjectAccessReview; API server connectivity issues mid-session.","solutions":["Ask the operator for patch permission: add verbs [\"get\",\"patch\"] for the resource(verbs include \"patch\") in a Role/ClusterRole bound to the user.","Verify with kubectl auth can-i patch <resource> <name> -n <ns> to distinguish RBAC denial from an API error.","If CanI errors rather than denies, fix connectivity/apiserver/admission issue and retry; check kube-apiserver logs for SelfSubjectAccessReview failures.","If read-only access is intentional, view YAML instead of editing (y key or equivalent)."],"exampleFix":"# before: role allows read-only\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nrules:\n- apiGroups: [\"\"]\n  resources: [\"services\"]\n  verbs: [\"get\",\"list\",\"watch\"]\n\n# after: add patch for editing\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nrules:\n- apiGroups: [\"\"]\n  resources: [\"services\"]\n  verbs: [\"get\",\"list\",\"watch\",\"patch\"]","handlingStrategy":"validation","validationCode":"if ok, err := app.Conn().CanI(ns, gvr, n, client.PatchAccess); err != nil {\n    return fmt.Errorf(\"permission check failed for %s: %w\", gvr, err)\n} else if !ok {\n    return fmt.Errorf(\"rbac: patch denied on %s/%s, ask operator for patch verb\", ns, gvr)\n}","typeGuard":null,"tryCatchPattern":"if err := editRes(app, gvr, path); err != nil {\n    if strings.Contains(err.Error(), \"can't edit\") {\n    // verify out-of-band to distinguish denial vs API failure\n    _ = shellRun(app, \"kubectl auth can-i patch \" + gvr.String() + \" -n \" + ns)\n    }\n}","preventionTips":["Run kubectl auth can-i patch <res> <name> before sessions on clusters with tight RBAC.","Treat CanI errors and denials differently in code: wrap and log err instead of collapsing into one message.","Keep read-only users away from edit keybindings via keybinding config."],"tags":["kubernetes","rbac","edit","authorization"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}