derailed/k9s · warning
access denied for user on: %s/%s
Error message
access denied for user on: %s/%s
What it means
Namespace quick-switch (typing a namespace's index digit) checks CanI(ns, gvr, "", ListAccess) for the current GVR; it returned false. The user can see the namespace in the favorites/switch list but cannot list the currently viewed resource type there, so the switch is blocked. If err is non-nil the flash shows the raw error instead.
Source
Thrown at internal/view/browser.go:593
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)
return nil
}
ns := b.namespaces[i]
auth, err := b.App().factory.Client().CanI(ns, b.GVR(), "", client.ListAccess)
if !auth {
if err == nil {
err = fmt.Errorf("access denied for user on: %s/%s", ns, b.GVR())
}
b.App().Flash().Err(err)
return nil
}
if err := b.app.switchNS(ns); err != nil {
b.App().Flash().Err(err)
return nil
}
b.setNamespace(ns)
if client.IsClusterScoped(ns) {
b.app.Flash().Infof("Viewing %s...", b.GVR())
} else {
b.app.Flash().Infof("Viewing %s in namespace `%s`...", b.GVR(), client.PrintNamespace(ns))
}
b.refresh()
b.UpdateTitle()
b.SelectRow(1, 0, true)View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Run kubectl auth can-i list <resource> -n <namespace> to confirm the denial.
- Request list permission for the GVR in that namespace (Role with verbs ["list"], or list at cluster scope for cluster-scoped GVRs).
- Switch to a GVR you can list everywhere (e.g. namespaces) before quick-switching, or use the namespace picker over a permitted resource.
- Remove stale namespace favorites bound to namespaces you no longer access.
Defensive patterns
Strategy: validation
Validate before calling
auth, err := b.App().factory.Client().CanI(ns, b.GVR(), "", client.ListAccess)
if err != nil {
b.App().Flash().Err(err)
return nil
}
if !auth {
b.App().Flash().Errf("no list access on %s in %s", b.GVR(), ns)
return nil
} Prevention
- Bind namespace quick-switch keys only to namespaces the token can list for common GVRs.
- Check CanI on the active GVR before registering number-key bindings.
- On role changes, restart the session so favorites and RBAC stay in sync.
When it happens
Trigger: Pressing a number key bound to b.namespaces[i] while the active browser's GVR is not listable in that namespace (Role grants list only in other namespaces; namespace-stage RBAC; cluster-scoped resource with namespace-filtered roles).
Common situations: Per-namespace RBAC segregation (team A's namespaces vs team B's); switching while on a cluster-scoped custom resource; stale favorites referencing namespaces the token lost after a role change.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- user is not authorized to list pods metrics
- ACCESS -- No API server connection
- no metrics-server detected on cluster
- user is not authorized to list node metrics
- user is not authorized to list pod metrics
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/2088466e0a3f3acd.
Report an issue: GitHub.