{"record":{"id":"6d6d572068760e7f","repo":"derailed/k9s","slug":"user-is-not-authorized-to-list-nodes","errorCode":null,"errorMessage":"user is not authorized to list nodes","messagePattern":"user is not authorized to list nodes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/node.go","lineNumber":276,"sourceCode":"\tif err != nil {\n\t\treturn false, err\n\t}\n\n\treturn o.Spec.Unschedulable, nil\n}\n\n// ----------------------------------------------------------------------------\n// Helpers...\n\n// FetchNode retrieves a node.\nfunc FetchNode(_ context.Context, f Factory, path string) (*v1.Node, error) {\n\t_, n := client.Namespaced(path)\n\tauth, err := f.Client().CanI(client.ClusterScope, client.NodeGVR, n, client.GetAccess)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif !auth {\n\t\treturn nil, fmt.Errorf(\"user is not authorized to list nodes\")\n\t}\n\n\to, err := f.Get(client.NodeGVR, client.FQN(client.ClusterScope, path), true, labels.Everything())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar node v1.Node\n\terr = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &node)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &node, nil\n}\n\n// FetchNodes retrieves all nodes.\nfunc FetchNodes(_ context.Context, f Factory, _ string) (*v1.NodeList, error) {","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/node.go#L258-L294","documentation":"FetchNode gates the read with a CanI authorization check for the get verb on the nodes resource at cluster scope and returns this error when access is denied. Note the message says \"list\" although the check actually performed is a get on a single named node — a wording quirk in the DAO.","triggerScenarios":"CanI(cluster-scope, nodes, <name>, get) returns false — the kubeconfig user lacks the get verb on core nodes.","commonSituations":"Restricted service accounts (CI runners, GitOps) with only namespace-scoped roles; kubeconfig using a tenant/limited user; policy engines (OPA/Kyverno) denying node reads; users misled by the 'list' wording into granting the wrong verb.","solutions":["Grant node read access: a ClusterRole with apiGroups [\"\"] resources [\"nodes\"] verbs [\"get\",\"list\"] (or bind the built-in view ClusterRole)","Verify as the same user: kubectl auth can-i get nodes","Switch to a kubeconfig context with cluster read if node inspection is required"],"exampleFix":"apiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: node-reader\nrules:\n- apiGroups: [\"\"]\n  resources: [\"nodes\"]\n  verbs: [\"get\", \"list\"]","handlingStrategy":"validation","validationCode":"ok, err := factory.Client().CanI(client.ClusterScope, client.NodeGVR, nodeName, client.GetAccess)\nif err != nil { return err }\nif !ok { return fmt.Errorf(\"missing get on nodes for this identity\") }","typeGuard":null,"tryCatchPattern":"if _, err := dao.FetchNode(ctx, f, path); err != nil {\n    if strings.Contains(err.Error(), \"not authorized to list nodes\") {\n        // terminal RBAC gap: stop and prompt for credentials/role, do not retry\n    }\n}","preventionTips":["Run kubectl auth can-i get nodes as a preflight for any node-dependent feature","Grant get+list on nodes together — the DAO needs both across its node APIs","Remember this message can mean 'get' denied even though it says list"],"tags":["kubernetes","rbac","node","authorization"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}