{"record":{"id":"8baf153d09e6c8f1","repo":"GoogleContainerTools/skaffold","slug":"initializing-deployment-watcher-s","errorCode":null,"errorMessage":"initializing deployment watcher: %s","messagePattern":"initializing deployment watcher: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/kubernetes/wait.go","lineNumber":143,"sourceCode":"\t\t\t}\n\t\t}\n\t\treturn false, nil\n\t})\n}\n\n// WaitForDeploymentToStabilize waits until the Deployment has a matching generation/replica count between spec and status.\nfunc WaitForDeploymentToStabilize(ctx context.Context, c kubernetes.Interface, ns, name string, timeout time.Duration) error {\n\tlog.Entry(ctx).Infof(\"Waiting for %s to stabilize\", name)\n\n\tfields := fields.Set{\n\t\t\"metadata.name\":      name,\n\t\t\"metadata.namespace\": ns,\n\t}\n\tw, err := c.AppsV1().Deployments(ns).Watch(ctx, metav1.ListOptions{\n\t\tFieldSelector: fields.AsSelector().String(),\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"initializing deployment watcher: %s\", err)\n\t}\n\n\treturn watchUntilTimeout(ctx, timeout, w, func(event *watch.Event) (bool, error) {\n\t\tif event.Type == watch.Deleted {\n\t\t\treturn false, apierrs.NewNotFound(schema.GroupResource{Resource: \"deployments\"}, \"\")\n\t\t}\n\n\t\tif dp, ok := event.Object.(*appsv1.Deployment); ok {\n\t\t\tif dp.Name == name && dp.Namespace == ns &&\n\t\t\t\tdp.Generation <= dp.Status.ObservedGeneration &&\n\t\t\t\t*(dp.Spec.Replicas) == dp.Status.Replicas {\n\t\t\t\treturn true, nil\n\t\t\t}\n\t\t\tglog.Infof(\"Waiting for deployment %s to stabilize, generation %v observed generation %v spec.replicas %d status.replicas %d\",\n\t\t\t\tname, dp.Generation, dp.Status.ObservedGeneration, *(dp.Spec.Replicas), dp.Status.Replicas)\n\t\t}\n\t\treturn false, nil\n\t})","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/kubernetes/wait.go#L125-L161","documentation":"WaitForDeploymentToStabilize starts a Watch on the AppsV1 Deployments API for the target namespace; if that watch request fails it is wrapped as 'initializing deployment watcher: %s'. The failure happens before any stability evaluation, so it reflects API-server access issues (connectivity, auth, RBAC) for the deployments resource.","triggerScenarios":"Calling WaitForDeploymentToStabilize when c.AppsV1().Deployments(ns).Watch() errors: API server unreachable, expired credentials, or RBAC denying watch on deployments in namespace ns.","commonSituations":"Service account limited to pods only (no deployments RBAC) in a hardened cluster; token expiry during a long session; kubeconfig pointing at the wrong namespace/cluster; flaky cluster networking in CI.","solutions":["Verify access: `kubectl get deployments -n <ns>` with the same credentials; fix kubeconfig if it fails","Grant RBAC watch on deployments: add apps/deployments with get,list,watch verbs to the role binding","Refresh credentials (re-authenticate with the cloud provider, update the token)","Check API-server reachability/VPN and retry"],"exampleFix":"// before (RBAC)\nresources: [\"pods\"]\n// after\nresources: [\"pods\", \"deployments\"]","handlingStrategy":"retry","validationCode":"// check deployments watch permission up front\n_, err := client.AppsV1().Deployments(ns).List(ctx, metav1.ListOptions{})\nif err != nil {\n    return fmt.Errorf(\"deployments API not accessible in %s: %w\", ns, err)\n}","typeGuard":null,"tryCatchPattern":"err := kubernetes.WaitForDeploymentToStabilize(ctx, client, ns, name, timeout)\nif err != nil {\n    if apierrors.IsForbidden(err) || apierrors.IsUnauthorized(err) {\n        if rerr := refreshCredentials(ctx); rerr == nil {\n            err = kubernetes.WaitForDeploymentToStabilize(ctx, client, ns, name, timeout)\n        }\n    }\n}\nreturn err","preventionTips":["Include apps/deployments get,list,watch in RBAC roles used by skaffold","Refresh long-lived tokens before long deploy sessions","Pin the correct namespace/cluster in kubeconfig for CI runners","Alert on API-server flakiness in CI networks"],"tags":["kubernetes","watch","rbac"],"backgroundTag":"kubernetes-api-unreachable","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"}