{"record":{"id":"e93dda58e20f1815","repo":"GoogleContainerTools/skaffold","slug":"listing-pods-w","errorCode":null,"errorMessage":"listing pods: %w","messagePattern":"listing pods: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/kubernetes/portforward/kubectl_forwarder.go","lineNumber":283,"sourceCode":"\tsvc, err := client.CoreV1().Services(ns).Get(ctx, serviceName, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn \"\", -1, fmt.Errorf(\"getting service %s/%s: %w\", ns, serviceName, err)\n\t}\n\tsvcPort, err := findServicePort(*svc, servicePort)\n\tif err != nil {\n\t\treturn \"\", -1, err\n\t}\n\n\t// Look for pods with matching selectors and that are not terminated.\n\t// We cannot use field selectors as they are only supported in 1.16\n\t// https://github.com/flant/shell-operator/blob/8fa3c3b8cfeb1ddb37b070b7a871561fdffe788b/HOOKS.md#fieldselector\n\tset := labels.Set(svc.Spec.Selector)\n\tlistOptions := metav1.ListOptions{\n\t\tLabelSelector: set.AsSelector().String(),\n\t}\n\tpodsList, err := client.CoreV1().Pods(ns).List(ctx, listOptions)\n\tif err != nil {\n\t\treturn \"\", -1, fmt.Errorf(\"listing pods: %w\", err)\n\t}\n\tvar pods []corev1.Pod\n\tfor _, pod := range podsList.Items {\n\t\tif pod.Status.Phase == corev1.PodPending || pod.Status.Phase == corev1.PodRunning {\n\t\t\tpods = append(pods, pod)\n\t\t}\n\t}\n\tsort.Slice(pods, newestPodsFirst(pods))\n\n\tif log.IsTraceLevelEnabled() {\n\t\tvar names []string\n\t\tfor _, p := range pods {\n\t\t\tnames = append(names, fmt.Sprintf(\"(pod:%q phase:%v created:%v)\", p.Name, p.Status.Phase, p.CreationTimestamp))\n\t\t}\n\t\tlog.Entry(ctx).Tracef(\"service %s/%s maps to %d pods: %v\", serviceName, servicePort.String(), len(pods), names)\n\t}\n\n\tfor _, p := range pods {","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/kubernetes/portforward/kubectl_forwarder.go#L265-L301","documentation":"After locating the Service, the forwarder lists Pods in the namespace filtered by the service's spec.selector label selector. If the Pods List call fails, the error is wrapped as \"listing pods: <cause>\". This indicates the cluster query for backing pods itself failed, not that pods were absent.","triggerScenarios":"client.CoreV1().Pods(ns).List(ctx, listOptions) with LabelSelector derived from svc.Spec.Selector returns an error: RBAC denies pods list, API server timeout/disconnect, context canceled while shutting down, or invalid label selector characters in the service selector.","commonSituations":"Flaky network to a remote cluster during `skaffold dev`; RBAC-restricted namespaces (CI service accounts lacking pod list); cluster upgrade causing temporary API unavailability; ctrl-C canceling the request concurrently.","solutions":["Test `kubectl get pods -n <ns> -l <selector>` succeeds with the same credentials; fix RBAC if forbidden.","Check cluster/API server health and network stability (`kubectl cluster-info`, VPN).","Retry skaffold dev if the failure was a transient timeout.","Ensure the service's selector labels are valid Kubernetes label values (no illegal characters)."],"exampleFix":"// before: CI service account without pod read access\nrules: []\n// after\nrules:\n- apiGroups: [\"\"]\n  resources: [\"pods\", \"services\"]\n  verbs: [\"get\", \"list\", \"watch\"]","handlingStrategy":"retry","validationCode":"// preflight: can the identity list pods in the namespace?\n_, err := client.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{Limit: 1})\nif err != nil {\n    return fmt.Errorf(\"RBAC/connectivity preflight failed in ns %s: %w\", ns, err)\n}","typeGuard":"func isTransientListErr(err error) bool {\n    return apierrors.IsTimeout(err) || apierrors.IsServerTimeout(err) ||\n        apierrors.IsTooManyRequests(err) || errors.Is(err, context.Canceled) == false && neterr := true\n}","tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n    pod, port, err := findNewestPodForService(ctx, kubeContext, ns, svc, p)\n    if err == nil { break }\n    if strings.Contains(err.Error(), \"listing pods\") && attempt < 2 {\n        time.Sleep(time.Duration(1<<attempt) * time.Second) // backoff for transient API errors\n        continue\n    }\n    return err\n}","preventionTips":["Grant `list`/`watch` on pods to the identity skaffold authenticates as.","Keep VPN/network stable when targeting remote clusters; prefer contexts with low latency.","Watch for API server maintenance windows/upgrades that cause transient list failures."],"tags":["kubernetes","rbac","api-server"],"backgroundTag":"kubernetes-list-forbidden","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}