GoogleContainerTools/skaffold · error

could not fetch deployments: %w

Error message

could not fetch deployments: %w

What it means

getDeployments wraps any error from listing Deployments (client.AppsV1().Deployments(ns).List with the run-id label selector) with 'could not fetch deployments'. statusCheck converts it to STATUSCHECK_DEPLOYMENT_FETCH_ERR. The wrapped cause is the raw Kubernetes client error (network, RBAC, timeout).

Source

Thrown at pkg/skaffold/kubernetes/status/status_check.go:348

	for _, r := range uRes {
		resName := r.GroupVersionKind().String()
		if r.GetName() != "" {
			resName = fmt.Sprintf("%s, Name=%s", resName, r.GetName())
		}
		pd := diag.New([]string{ns}).
			WithValidators([]validator.Validator{validator.NewCustomValidator(client, dynClient, r.GroupVersionKind())})
		result = append(result, resource.NewResource(resName, resource.ResourceTypes.CustomResource, ns, deadlineDuration, tolerateFailures).WithValidator(pd))
	}

	return result, nil
}

func getDeployments(ctx context.Context, client kubernetes.Interface, ns string, l *label.DefaultLabeller, deadlineDuration time.Duration, tolerateFailures bool) ([]*resource.Resource, error) {
	deps, err := client.AppsV1().Deployments(ns).List(ctx, metav1.ListOptions{
		LabelSelector: l.RunIDSelector(),
	})
	if err != nil {
		return nil, fmt.Errorf("could not fetch deployments: %w", err)
	}

	resources := make([]*resource.Resource, len(deps.Items))
	for i, d := range deps.Items {
		var deadline time.Duration
		if d.Spec.ProgressDeadlineSeconds == nil || *d.Spec.ProgressDeadlineSeconds == kubernetesMaxDeadline {
			deadline = deadlineDuration
		} else {
			deadline = time.Duration(*d.Spec.ProgressDeadlineSeconds) * time.Second
		}

		pd := diag.New([]string{d.Namespace}).
			WithLabel(label.RunIDLabel, l.Labels()[label.RunIDLabel]).
			WithValidators([]validator.Validator{validator.NewPodValidator(client, validator.NewDeploymentPodsSelector(client, d))})

		for k, v := range d.Spec.Template.Labels {
			pd = pd.WithLabel(k, v)
		}

View on GitHub (pinned to a1189de023)

Solutions

  1. Reproduce the raw call: 'kubectl get deployments -n <ns> -l <run-id-selector>' and read the wrapped error
  2. Fix connectivity/credentials: refresh kubeconfig (e.g. gcloud container clusters get-credentials) and re-authenticate
  3. Fix RBAC if 403: grant get/list/watch on deployments.apps in the namespace
  4. Verify the namespace exists and the context matches the deployed cluster
  5. Increase statusCheck deadline or retry once the API server is responsive

Example fix

// before: stale CI kubeconfig pointing at old cluster
//   kubectl config use-context old-cluster
// after:
//   gcloud container clusters get-credentials my-cluster --region us-central1
//   kubectl config use-context my-cluster
Defensive patterns

Strategy: retry

Validate before calling

const ctxOk = execSync('kubectl config current-context').toString().trim();
const nsOk = execSync(`kubectl get ns ${ns} --request-timeout=10s`).toString();
const canList = execSync(`kubectl auth can-i list deployments.apps -n ${ns}`).toString().trim();
if (canList !== 'yes') throw new Error(`RBAC: cannot list deployments in ${ns} (ctx=${ctxOk})`);

Type guard

function isDeploymentFetchErr(err) {
  return err != null && typeof err.message === 'string' && err.message.includes('could not fetch deployments');
}

Try / catch

for (let attempt = 0; attempt < 3; attempt++) {
  try { await statusCheck(); break; }
  catch (err) {
    if (isDeploymentFetchErr(err) && /timeout|connection refused|connection reset/i.test(err.message) && attempt < 2) {
      await sleep(2000 * (attempt + 1));
      continue;
    }
    throw err;
  }
}

Prevention

When it happens

Trigger: Deployments List call fails for a namespace: connection refused/timeout to API server, 403 on list deployments.apps, nonexistent namespace, context pointing to wrong cluster, or context deadline exceeded before getDeadline.

Common situations: kubeconfig switched to a cluster without the deployed app; CI runner losing network to the control plane; RBAC roles missing deployments.apps; expired cloud credentials; namespace deleted mid-run.

Related errors


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