derailed/k9s · error
user is not authorized to list pods metrics
Error message
user is not authorized to list pods metrics
What it means
Raised at internal/client/metrics.go:100 inside checkAccess when the RBAC check for pods.metrics.k8s.io in a namespace returns auth=false. The message string is the const in FetchPodsMetrics (metrics.go:232); the check runs at metrics.go:237 against PmxGVR in the (possibly BlankNamespace for all-namespaces) scope. It indicates the connection is healthy and metrics-server exists, but the user cannot list pod metrics in that namespace.
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
- Add a Role/ClusterRole granting get/list on pods.metrics.k8s.io and bind it in the target namespace(s) (kubectl auth can-i list pods.metrics.k8s.io -n ns to verify)
- For all-namespaces browsing, use a ClusterRoleBinding instead of per-namespace RoleBindings
- If denial is intended, disable/skip metrics columns and pulse for that user
Example fix
// before
mx, err := metricsSrv.FetchPodsMetrics(ctx, ns)
// after
auth, err := metricsSrv.CanI(ns, client.PmxGVR, "", client.ListAccess)
if err == nil && !auth {
return nil, nil // degrade: no pod-metrics permission in ns
}
mx, err := metricsSrv.FetchPodsMetrics(ctx, ns) Defensive patterns
Strategy: validation
Validate before calling
auth, err := metricsSrv.CanI(ns, client.PmxGVR, "", client.ListAccess)
if err == nil && !auth {
return nil, nil // skip metrics for this namespace
}
mx, err := metricsSrv.FetchPodsMetrics(ctx, ns) Try / catch
if _, err := metricsSrv.FetchPodsMetrics(ctx, ns); err != nil {
if strings.Contains(err.Error(), "not authorized to list pods metrics") {
// blank the metrics columns for ns; suggest RoleBinding fix
}
} Prevention
- Cache per-namespace CanI results for the session to avoid repeated reviews
- Add pods.metrics.k8s.io to namespaced Roles you hand to teams
- For all-namespace views, require the cluster-scoped grant up front
When it happens
Trigger: Calling FetchPodsMetrics(ctx, ns) (directly or via FetchPodsMetricsMap) when CanI(ns, PmxGVR, "", [list]) is false; also hit when browsing pods in 'all namespaces' mode where ns becomes BlankNamespace and a cluster-wide grant is required.
Common situations: Namespace-scoped users whose RoleBindings cover deployments/pods but not the metrics.k8s.io group; all-namespace view without a ClusterRole for pods.metrics.k8s.io; k9s pulse view opened by an on-call account with minimal grants.
Related errors
- user is not authorized to list node 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/3ae7098648e22b95.
Report an issue: GitHub.