{"record":{"id":"4457c2462e266b98","repo":"GoogleContainerTools/skaffold","slug":"could-not-fetch-stateful-sets-w","errorCode":null,"errorMessage":"could not fetch stateful sets: %w","messagePattern":"could not fetch stateful sets: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/kubernetes/status/status_check.go","lineNumber":378,"sourceCode":"\t\tpd := diag.New([]string{d.Namespace}).\n\t\t\tWithLabel(label.RunIDLabel, l.Labels()[label.RunIDLabel]).\n\t\t\tWithValidators([]validator.Validator{validator.NewPodValidator(client, validator.NewDeploymentPodsSelector(client, d))})\n\n\t\tfor k, v := range d.Spec.Template.Labels {\n\t\t\tpd = pd.WithLabel(k, v)\n\t\t}\n\n\t\tresources[i] = resource.NewResource(d.Name, resource.ResourceTypes.Deployment, d.Namespace, deadline, tolerateFailures).WithValidator(pd)\n\t}\n\treturn resources, nil\n}\n\nfunc getStatefulSets(ctx context.Context, client kubernetes.Interface, ns string, l *label.DefaultLabeller, deadline time.Duration, tolerateFailures bool) ([]*resource.Resource, error) {\n\tsets, err := client.AppsV1().StatefulSets(ns).List(ctx, metav1.ListOptions{\n\t\tLabelSelector: l.RunIDSelector(),\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not fetch stateful sets: %w\", err)\n\t}\n\n\tresources := make([]*resource.Resource, len(sets.Items))\n\tfor i, ss := range sets.Items {\n\t\tpd := diag.New([]string{ss.Namespace}).\n\t\t\tWithLabel(label.RunIDLabel, l.Labels()[label.RunIDLabel]).\n\t\t\tWithValidators([]validator.Validator{validator.NewPodValidator(client, validator.NewStatefulSetPodsSelector(client, ss))})\n\n\t\tfor k, v := range ss.Spec.Template.Labels {\n\t\t\tpd = pd.WithLabel(k, v)\n\t\t}\n\n\t\tresources[i] = resource.NewResource(ss.Name, resource.ResourceTypes.StatefulSet, ss.Namespace, deadline, tolerateFailures).WithValidator(pd)\n\t}\n\treturn resources, nil\n}\n\nfunc pollResourceStatus(ctx context.Context, cfg Config, r *resource.Resource) {","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/kubernetes/status/status_check.go#L360-L396","documentation":"getStatefulSets wraps any error from client.AppsV1().StatefulSets(ns).List (run-id label selector) with 'could not fetch stateful sets'. Note the slightly different wording from the statusCheck-level wrapper ('statefulsets'). statusCheck reports it as STATUSCHECK_STATEFULSET_FETCH_ERR.","triggerScenarios":"StatefulSets List call fails per namespace: API server unreachable, RBAC denial on statefulsets.apps, missing namespace, or timeout against getDeadline.","commonSituations":"Cluster roles granting deployments but not statefulsets; VPN disconnect during status check; wrong namespace in config; cluster control plane overloaded/unreachable right after deploy.","solutions":["Reproduce with 'kubectl get statefulsets -n <ns>' using the same kubeconfig","Grant statefulsets.apps get/list/watch in RBAC if the error is 403","Verify namespace and current context are correct","Restore network/VPN to the control plane and refresh credentials","Retry the status check once the API server responds"],"exampleFix":"// before: role without statefulsets access\n//   kubectl create role ci --verb=get,list --resource=deployments.apps,pods\n// after:\n//   kubectl create role ci --verb=get,list,watch --resource=deployments.apps,pods,statefulsets.apps","handlingStrategy":"retry","validationCode":"const canList = execSync(`kubectl auth can-i list statefulsets.apps -n ${ns}`).toString().trim();\nif (canList !== 'yes') throw new Error(`RBAC: cannot list statefulsets in ${ns}`);\nexecSync(`kubectl get statefulsets -n ${ns} --request-timeout=10s`);","typeGuard":"function isStatefulSetsFetchErr(err) {\n  return err != null && typeof err.message === 'string' && err.message.includes('could not fetch stateful sets');\n}","tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try { await statusCheck(); break; }\n  catch (err) {\n    if (isStatefulSetsFetchErr(err) && /timeout|unreachable|connection/i.test(err.message) && attempt < 2) {\n      await sleep(2000 * (attempt + 1));\n      continue;\n    }\n    throw err;\n  }\n}","preventionTips":["Include statefulsets.apps in CI RBAC roles","Pre-flight 'kubectl get statefulsets -n <ns>' before long status checks","Refresh credentials before pipeline status phases","Retry on transient control-plane unavailability"],"tags":["kubernetes","statefulset","rbac","api-server"],"backgroundTag":"kubernetes-api-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"}