{"record":{"id":"1f246848d9a7dd30","repo":"derailed/k9s","slug":"v-access-denied-on-resource-q-q","errorCode":null,"errorMessage":"%v access denied on resource %q:%q","messagePattern":"(.+?) access denied on resource %q:%q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/watch/factory.go","lineNumber":213,"sourceCode":"\tf.mx.RLock()\n\tdefer f.mx.RUnlock()\n\t_, ok := f.factories[client.BlankNamespace]\n\n\treturn ok\n}\n\n// CanForResource return an informer is user has access.\nfunc (f *Factory) CanForResource(ns string, gvr *client.GVR, verbs []string) (informers.GenericInformer, error) {\n\tvar resName string\n\tif gvr == client.NsGVR {\n\t\tresName = ns\n\t}\n\tauth, err := f.Client().CanI(ns, gvr, resName, verbs)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !auth {\n\t\treturn nil, fmt.Errorf(\"%v access denied on resource %q:%q\", verbs, ns, gvr)\n\t}\n\n\t// Namespaces are cluster-scoped; always use cluster scope for the informer\n\tif gvr == client.NsGVR {\n\t\tns = client.ClusterScope\n\t}\n\n\treturn f.ForResource(ns, gvr)\n}\n\n// CanForInstance return an informer is user has access.\nfunc (f *Factory) CanForInstance(fqn string, gvr *client.GVR, verbs []string) (informers.GenericInformer, error) {\n\tns, n := namespaced(fqn)\n\tif client.IsAllNamespace(ns) {\n\t\tns = client.BlankNamespace\n\t}\n\n\t// For namespace resources, use the resource name as the namespace for RBAC","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/watch/factory.go#L195-L231","documentation":"Factory.CanForResource (internal/watch/factory.go:213) performs a SelfSubjectAccessReview (Client().CanI) for the given verbs on a resource in a namespace. When the server answers 'not allowed', k9s refuses to create an informer and returns this error listing the verbs, namespace and GVR. It is an RBAC denial surfaced before any watch/list attempt.","triggerScenarios":"Opening a view / running a feature that needs informers on a resource the current user has no get/list/watch (or the specific requested verbs) for in that namespace — e.g. ':events' with no list on events, xray on a cluster where the user is namespace-restricted.","commonSituations":"Restricted service-account kubeconfigs (CI, read-only auditor roles); missing RoleBinding for a new team member; typos in Role resourceNames; freshly created namespace without bindings; cluster-scope-only users browsing other namespaces.","solutions":["Identify the missing verbs from the message and grant them via Role + RoleBinding in that namespace (see exampleFix)","Verify current identity and permissions: 'kubectl auth whoami' and 'kubectl auth can-i --list -n <ns>'","Run k9s with a kubeconfig that has broader rights, or point KUBECONFIG at the right context","If denial is expected, avoid navigating to that resource view; k9s only calls CanForResource for features you invoke"],"exampleFix":"# before: [get list watch] access denied on resource \"ns1\":\"apps/v1/deployments\"\n# after: grant RBAC\nkind: Role\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: deploy-viewer\n  namespace: ns1\nrules:\n  - apiGroups: [\"apps\"]\n    resources: [\"deployments\"]\n    verbs: [\"get\", \"list\", \"watch\"]\n---\nkind: RoleBinding\napiVersion: rbac.authorization.k8s.io/v1\nmetadata:\n  name: deploy-viewer-binding\n  namespace: ns1\nsubjects:\n  - kind: User\n    name: jane\nroleRef:\n  kind: Role\n  name: deploy-viewer\n  apiGroup: rbac.authorization.k8s.io","handlingStrategy":"try-catch","validationCode":"// pre-check with the same SSAR call before building UI on the informer\nif ok, err := f.Client().CanI(ns, gvr, \"\", []string{\"get\", \"list\", \"watch\"}); err == nil && !ok {\n    // hide/disable the feature instead of erroring later\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Go: treat the denial as a control-flow signal, not a crash\ninf, err := f.CanForResource(ns, gvr, verbs)\nif err != nil {\n    if strings.Contains(err.Error(), \"access denied\") {\n        slog.Warn(\"rbac denied\", slog.String(\"gvr\", gvr.String()), slog.String(\"ns\", ns))\n        return hideFeature(gvr)\n    }\n    return err\n}","preventionTips":["Audit RBAC with 'kubectl auth can-i --list -n <ns>' before pointing k9s at a cluster","Maintain per-team RoleBindings that include get/list/watch for resources the team browses","Programmatically call kubectl auth can-i before enabling resource features in tooling"],"tags":["k9s","rbac","kubernetes","authorization","informer"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}