GoogleContainerTools/skaffold · error

listing pods: %w

Error message

listing pods: %w

What it means

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.

Source

Thrown at pkg/skaffold/kubernetes/portforward/kubectl_forwarder.go:283

	svc, err := client.CoreV1().Services(ns).Get(ctx, serviceName, metav1.GetOptions{})
	if err != nil {
		return "", -1, fmt.Errorf("getting service %s/%s: %w", ns, serviceName, err)
	}
	svcPort, err := findServicePort(*svc, servicePort)
	if err != nil {
		return "", -1, err
	}

	// Look for pods with matching selectors and that are not terminated.
	// We cannot use field selectors as they are only supported in 1.16
	// https://github.com/flant/shell-operator/blob/8fa3c3b8cfeb1ddb37b070b7a871561fdffe788b/HOOKS.md#fieldselector
	set := labels.Set(svc.Spec.Selector)
	listOptions := metav1.ListOptions{
		LabelSelector: set.AsSelector().String(),
	}
	podsList, err := client.CoreV1().Pods(ns).List(ctx, listOptions)
	if err != nil {
		return "", -1, fmt.Errorf("listing pods: %w", err)
	}
	var pods []corev1.Pod
	for _, pod := range podsList.Items {
		if pod.Status.Phase == corev1.PodPending || pod.Status.Phase == corev1.PodRunning {
			pods = append(pods, pod)
		}
	}
	sort.Slice(pods, newestPodsFirst(pods))

	if log.IsTraceLevelEnabled() {
		var names []string
		for _, p := range pods {
			names = append(names, fmt.Sprintf("(pod:%q phase:%v created:%v)", p.Name, p.Status.Phase, p.CreationTimestamp))
		}
		log.Entry(ctx).Tracef("service %s/%s maps to %d pods: %v", serviceName, servicePort.String(), len(pods), names)
	}

	for _, p := range pods {

View on GitHub (pinned to a1189de023)

Solutions

  1. Test `kubectl get pods -n <ns> -l <selector>` succeeds with the same credentials; fix RBAC if forbidden.
  2. Check cluster/API server health and network stability (`kubectl cluster-info`, VPN).
  3. Retry skaffold dev if the failure was a transient timeout.
  4. Ensure the service's selector labels are valid Kubernetes label values (no illegal characters).

Example fix

// before: CI service account without pod read access
rules: []
// after
rules:
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "watch"]
Defensive patterns

Strategy: retry

Validate before calling

// preflight: can the identity list pods in the namespace?
_, err := client.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{Limit: 1})
if err != nil {
    return fmt.Errorf("RBAC/connectivity preflight failed in ns %s: %w", ns, err)
}

Type guard

func isTransientListErr(err error) bool {
    return apierrors.IsTimeout(err) || apierrors.IsServerTimeout(err) ||
        apierrors.IsTooManyRequests(err) || errors.Is(err, context.Canceled) == false && neterr := true
}

Try / catch

for attempt := 0; attempt < 3; attempt++ {
    pod, port, err := findNewestPodForService(ctx, kubeContext, ns, svc, p)
    if err == nil { break }
    if strings.Contains(err.Error(), "listing pods") && attempt < 2 {
        time.Sleep(time.Duration(1<<attempt) * time.Second) // backoff for transient API errors
        continue
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/e93dda58e20f1815. Report an issue: GitHub.