derailed/k9s · error
current user can't edit resource %s
Error message
current user can't edit resource %s
What it means
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.
Source
Thrown at internal/view/browser.go:567
b.App().Flash().Err(err)
}
return nil
}
func editRes(app *App, gvr *client.GVR, path string) error {
if path == "" {
return fmt.Errorf("nothing selected %q", path)
}
ns, n := client.Namespaced(path)
if n == "" {
return fmt.Errorf("missing resource name in path %q", path)
}
if client.IsClusterScoped(ns) {
ns = client.BlankNamespace
}
if ok, err := app.Conn().CanI(ns, gvr, n, client.PatchAccess); !ok || err != nil {
return fmt.Errorf("current user can't edit resource %s", gvr)
}
args := make([]string, 0, 10)
args = append(args, "edit", gvr.FQN(n))
if ns != client.BlankNamespace {
args = append(args, "-n", ns)
}
if err := runK(app, &shellOpts{clear: true, args: args}); err != nil {
app.Flash().Errf("Edit command failed: %s", err)
}
return nil
}
func (b *Browser) switchNamespaceCmd(evt *tcell.EventKey) *tcell.EventKey {
i, err := strconv.Atoi(string(evt.Rune()))
if err != nil {
slog.Error("Unable to convert keystroke", slogs.Error, err)View on GitHub (pinned to 2d3ccc6ba2)
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).
Example fix
# before: role allows read-only apiVersion: rbac.authorization.k8s.io/v1 kind: Role rules: - apiGroups: [""] resources: ["services"] verbs: ["get","list","watch"] # after: add patch for editing apiVersion: rbac.authorization.k8s.io/v1 kind: Role rules: - apiGroups: [""] resources: ["services"] verbs: ["get","list","watch","patch"]
Defensive patterns
Strategy: validation
Validate before calling
if ok, err := app.Conn().CanI(ns, gvr, n, client.PatchAccess); err != nil {
return fmt.Errorf("permission check failed for %s: %w", gvr, err)
} else if !ok {
return fmt.Errorf("rbac: patch denied on %s/%s, ask operator for patch verb", ns, gvr)
} Try / catch
if err := editRes(app, gvr, path); err != nil {
if strings.Contains(err.Error(), "can't edit") {
// verify out-of-band to distinguish denial vs API failure
_ = shellRun(app, "kubectl auth can-i patch " + gvr.String() + " -n " + ns)
}
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- user is not authorized to list node metrics
- user is not authorized to list pods metrics
- user is not authorized to list pod metrics
- (%s) access denied for user on resource %q:%s in namespace %
- user is not authorized to run jobs
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/6ee32a7e3e8f1ca2.
Report an issue: GitHub.