derailed/k9s · error

user is not authorized to list pod metrics

Error message

user is not authorized to list pod metrics

What it means

Raised at internal/client/metrics.go:100 inside checkAccess when the RBAC check for a single pod's metrics returns auth=false. The message string is the const in FetchPodMetrics (metrics.go:293), checked at :299; the call chain is typically FetchContainersMetrics -> FetchPodMetrics. Same GVR as [6] (pods.metrics.k8s.io) but the message marks the single-pod/containers path.

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

  1. Grant get/list on pods.metrics.k8s.io in the pod's namespace (Role + RoleBinding), verify with kubectl auth can-i list pods.metrics.k8s.io -n <ns>
  2. If per-pod detail is all that is needed, a namespaced Role is sufficient — no ClusterRole required
  3. Skip the containers-metrics UI when the check fails rather than surfacing the raw error

Example fix

// before
cmx, err := metricsSrv.FetchContainersMetrics(ctx, fqn)

// after
ns, _ := client.Namespaced(fqn)
auth, err := metricsSrv.CanI(ns, client.PmxGVR, "", client.ListAccess)
if err == nil && !auth {
    return nil, nil // user cannot view pod metrics; hide column data
}
cmx, err := metricsSrv.FetchContainersMetrics(ctx, fqn)
Defensive patterns

Strategy: validation

Validate before calling

ns, _ := client.Namespaced(fqn)
auth, err := metricsSrv.CanI(ns, client.PmxGVR, "", client.ListAccess)
if err == nil && !auth {
    return nil, nil // hide container metrics
}
cmx, err := metricsSrv.FetchContainersMetrics(ctx, fqn)

Try / catch

if _, err := metricsSrv.FetchContainersMetrics(ctx, fqn); err != nil {
    if strings.Contains(err.Error(), "not authorized to list pod metrics") {
        // render pod view without per-container usage columns
    }
}

Prevention

When it happens

Trigger: Calling FetchContainersMetrics(ctx, fqn) or FetchPodMetrics(ctx, fqn) for a pod whose namespace grants no list on pods.metrics.k8s.io — CanI(ns, PmxGVR, "", [list]) returns false.

Common situations: Opening a pod's containers-metrics view (shift+ins in k9s) as a user whose role covers core pods but not metrics.k8s.io; ns derived from the pod FQN being BlankNamespace during all-namespaces browsing.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/eda489393493847a. Report an issue: GitHub.