Home › Kubernetes

Error from server (Forbidden): User cannot list resource in API group at the cluster scope — how to fix

Error from server (Forbidden): pods is forbidden: User "jane@example.com" cannot list resource "pods" in API group "" in the namespace "default"
Error from server (Forbidden): nodes is forbidden: User "system:serviceaccount:ci:deployer" cannot list resource "nodes" in API group "" at the cluster scope

Quick fix: Check with kubectl auth can-i list pods -n <ns> and kubectl config current-context. Grant access: kubectl create role pod-reader --verb=get,list,watch --resource=pods -n <ns> then kubectl create rolebinding pod-reader-binding --role=pod-reader --user=<user> -n <ns> (or --serviceaccount=<ns>:<sa>). Use a ClusterRole + ClusterRoleBinding for cluster-scoped resources like nodes.

What it means

The message tells you exactly what's missing:

User "system:serviceaccount:ci:deployer" cannot list resource "nodes" in API group "" at the cluster scope
      ^ who                                    ^ verb        ^ resource  ^ group  ^ where

API group "" is the core group (pods, services, configmaps, secrets, nodes). Deployments are in apps, Ingresses in networking.k8s.io. The request passed authentication; it failed authorisation (RBAC). An authentication problem would say Unauthorized instead.

Step 1: confirm who you are and where

kubectl config current-context
kubectl config view --minify -o jsonpath='{..namespace}'; echo
kubectl auth whoami          # kubectl 1.28+
kubectl auth can-i list pods -n default
kubectl auth can-i --list -n default

Often the fix is just the namespace: you have rights in team-a, but your context defaults to default. Use -n team-a or:

kubectl config set-context --current --namespace=team-a

Fix 2: grant a namespaced Role

For resources inside a namespace (pods, deployments, secrets):

kubectl create role pod-reader --verb=get,list,watch --resource=pods -n team-a
kubectl create rolebinding pod-reader-binding --role=pod-reader --user=jane@example.com -n team-a

For a service account, bind with --serviceaccount=<namespace>:<name>:

kubectl create rolebinding deployer-edit --clusterrole=edit --serviceaccount=ci:deployer -n team-a

Binding a built-in ClusterRole (view, edit, admin) with a RoleBinding limits it to that namespace — a common, convenient pattern.

Fix 3: cluster-scoped resources

Nodes, namespaces, PersistentVolumes, CRDs and ClusterRoles aren't namespaced, so a Role can't grant them. Use a ClusterRole and ClusterRoleBinding:

kubectl create clusterrole node-reader --verb=get,list,watch --resource=nodes
kubectl create clusterrolebinding node-reader-binding --clusterrole=node-reader --serviceaccount=ci:deployer

Fix 4: pods calling the API

An app running in a pod uses its service account (default unless set). Give it its own:

apiVersion: v1
kind: ServiceAccount
metadata: { name: deployer, namespace: ci }
---
# in the Pod/Deployment spec
spec:
  serviceAccountName: deployer

then bind a role to ci:deployer as above. Test as that account:

kubectl auth can-i list pods -n team-a --as=system:serviceaccount:ci:deployer

Fix 5: managed clusters (EKS, GKE, AKS)

Least privilege

Avoid "fixing" this with cluster-admin. Grant only the verbs and resources needed, and prefer namespaced RoleBindings.

Last updated 2026-10-31.