derailed/k9s · error
user is not authorized to list node metrics
Error message
user is not authorized to list node metrics
What it means
Raised at internal/client/metrics.go:100 inside checkAccess when the RBAC check for the node-metrics GVR (nodes.metrics.k8s.io, checked at ClusterScope) returns auth=false. The message is the caller-supplied const in FetchNodesMetrics (metrics.go:152) and FetchNodeMetrics (:194). It means the user is connected and metrics-server exists, but lacks the list verb on nodes.metrics.k8s.io.
Source
Thrown at internal/client/metrics.go:100
tcpu += mx.AllocatableCPU
tmem += mx.AllocatableMEM
}
mx.PercCPU, mx.PercMEM = ToPercentage(ccpu, tcpu), ToPercentage(cmem, tmem)
return nil
}
func (m *MetricsServer) checkAccess(ns string, gvr *GVR, msg string) error {
if !m.HasMetrics() {
return errors.New("no metrics-server detected on cluster")
}
auth, err := m.CanI(ns, gvr, "", ListAccess)
if err != nil {
return err
}
if !auth {
return errors.New(msg)
}
return nil
}
// NodesMetrics retrieves metrics for a given set of nodes.
func (*MetricsServer) NodesMetrics(nodes *v1.NodeList, metrics *mv1beta1.NodeMetricsList, mmx NodesMetrics) {
if nodes == nil || metrics == nil {
return
}
for i := range nodes.Items {
mmx[nodes.Items[i].Name] = NodeMetrics{
AllocatableCPU: nodes.Items[i].Status.Allocatable.Cpu().MilliValue(),
AllocatableMEM: ToMB(nodes.Items[i].Status.Allocatable.Memory().Value()),
AllocatableEphemeral: ToMB(nodes.Items[i].Status.Allocatable.StorageEphemeral().Value()),
TotalCPU: nodes.Items[i].Status.Capacity.Cpu().MilliValue(),
TotalMEM: ToMB(nodes.Items[i].Status.Capacity.Memory().Value()),
TotalEphemeral: ToMB(nodes.Items[i].Status.Capacity.StorageEphemeral().Value()),View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Grant list/get on nodes.metrics.k8s.io via a ClusterRole + ClusterRoleBinding (e.g. the standard metrics-server scrapers view or kubectl create role/clusterrole with resource nodes.metrics.k8s.io)
- Verify with kubectl auth can-i list nodes.metrics.k8s.io
- If access is intentionally restricted, suppress the pulse/metrics views for this user instead of erroring
Example fix
// before
mx, err := metricsSrv.FetchNodesMetrics(ctx)
// after (defense: check first, degrade quietly)
auth, err := metricsSrv.CanI(client.ClusterScope, client.NmxGVR, "", client.ListAccess)
if err == nil && !auth {
return nil, nil // no metrics permission; skip node metrics
}
mx, err := metricsSrv.FetchNodesMetrics(ctx) Defensive patterns
Strategy: validation
Validate before calling
auth, err := metricsSrv.CanI(client.ClusterScope, client.NmxGVR, "", client.ListAccess)
if err == nil && !auth {
return nil, nil // degrade: hide node metrics
}
mx, err := metricsSrv.FetchNodesMetrics(ctx) Try / catch
if _, err := metricsSrv.FetchNodesMetrics(ctx); err != nil {
if strings.Contains(err.Error(), "not authorized to list node metrics") {
// hide pulse view / notify user about missing ClusterRole
}
} Prevention
- Pre-check CanI for nodes.metrics.k8s.io and remember per-user grants
- Include metrics.k8s.io resources in baseline cluster roles for operator groups
- Verify with kubectl auth can-i list nodes.metrics.k8s.io before filing bugs
When it happens
Trigger: Any call to FetchNodesMetrics or FetchNodeMetrics where CanI(ClusterScope, NmxGVR, "", [list]) returns false — i.e. no ClusterRole/Binding granting get/list on nodes.metrics.k8s.io.
Common situations: Restricted-view users provisioned only for core resources; operators on shared clusters where metrics are exposed only to SRE roles; fresh service-account used with k9s pulse view; cluster-role aggregation excluding metrics group.
Related errors
- user is not authorized to list pods metrics
- user is not authorized to list pod metrics
- no metrics-server detected on cluster
- (%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/d3b3afe60cc9112c.
Report an issue: GitHub.