{"record":{"id":"eda489393493847a","repo":"derailed/k9s","slug":"user-is-not-authorized-to-list-pod-metrics","errorCode":null,"errorMessage":"user is not authorized to list pod metrics","messagePattern":"user is not authorized to list pod metrics","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/metrics.go","lineNumber":100,"sourceCode":"\t\ttcpu += mx.AllocatableCPU\n\t\ttmem += mx.AllocatableMEM\n\t}\n\tmx.PercCPU, mx.PercMEM = ToPercentage(ccpu, tcpu), ToPercentage(cmem, tmem)\n\n\treturn nil\n}\n\nfunc (m *MetricsServer) checkAccess(ns string, gvr *GVR, msg string) error {\n\tif !m.HasMetrics() {\n\t\treturn errors.New(\"no metrics-server detected on cluster\")\n\t}\n\n\tauth, err := m.CanI(ns, gvr, \"\", ListAccess)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !auth {\n\t\treturn errors.New(msg)\n\t}\n\treturn nil\n}\n\n// NodesMetrics retrieves metrics for a given set of nodes.\nfunc (*MetricsServer) NodesMetrics(nodes *v1.NodeList, metrics *mv1beta1.NodeMetricsList, mmx NodesMetrics) {\n\tif nodes == nil || metrics == nil {\n\t\treturn\n\t}\n\n\tfor i := range nodes.Items {\n\t\tmmx[nodes.Items[i].Name] = NodeMetrics{\n\t\t\tAllocatableCPU:       nodes.Items[i].Status.Allocatable.Cpu().MilliValue(),\n\t\t\tAllocatableMEM:       ToMB(nodes.Items[i].Status.Allocatable.Memory().Value()),\n\t\t\tAllocatableEphemeral: ToMB(nodes.Items[i].Status.Allocatable.StorageEphemeral().Value()),\n\t\t\tTotalCPU:             nodes.Items[i].Status.Capacity.Cpu().MilliValue(),\n\t\t\tTotalMEM:             ToMB(nodes.Items[i].Status.Capacity.Memory().Value()),\n\t\t\tTotalEphemeral:       ToMB(nodes.Items[i].Status.Capacity.StorageEphemeral().Value()),","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/client/metrics.go#L82-L118","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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>","If per-pod detail is all that is needed, a namespaced Role is sufficient — no ClusterRole required","Skip the containers-metrics UI when the check fails rather than surfacing the raw error"],"exampleFix":"// before\ncmx, err := metricsSrv.FetchContainersMetrics(ctx, fqn)\n\n// after\nns, _ := client.Namespaced(fqn)\nauth, err := metricsSrv.CanI(ns, client.PmxGVR, \"\", client.ListAccess)\nif err == nil && !auth {\n    return nil, nil // user cannot view pod metrics; hide column data\n}\ncmx, err := metricsSrv.FetchContainersMetrics(ctx, fqn)","handlingStrategy":"validation","validationCode":"ns, _ := client.Namespaced(fqn)\nauth, err := metricsSrv.CanI(ns, client.PmxGVR, \"\", client.ListAccess)\nif err == nil && !auth {\n    return nil, nil // hide container metrics\n}\ncmx, err := metricsSrv.FetchContainersMetrics(ctx, fqn)","typeGuard":null,"tryCatchPattern":"if _, err := metricsSrv.FetchContainersMetrics(ctx, fqn); err != nil {\n    if strings.Contains(err.Error(), \"not authorized to list pod metrics\") {\n        // render pod view without per-container usage columns\n    }\n}","preventionTips":["Gate container-metrics views on the same CanI check the fetcher uses","Grant the metrics role in namespaces where users open pod details","Do not retry authorization errors — they are deterministic until RBAC changes"],"tags":["kubernetes","rbac","metrics-server","pods","authorization"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}