GoogleContainerTools/skaffold · error
attempting to watch verify job in cluster
Error message
attempting to watch verify job in cluster
What it means
watchJob failed to establish a Watch on the batch/v1 Job in the cluster. If the watch API call errors, the verify test is marked failed with 'attempting to watch verify job in cluster' wrapping the kube client error.
Solutions
- Verify RBAC: `kubectl auth can-i watch jobs -n <ns>` and add the missing role rules
- Confirm the job/namespace exist: `kubectl get jobs -n <ns>`
- Check kubeconfig/cluster connectivity and API server health
- Retry `skaffold verify`; if transient, the watch usually succeeds on rerun
Example fix
// before: role without watch rules: - apiGroups: ["batch"] resources: ["jobs"] verbs: ["create"] // after rules: - apiGroups: ["batch"] resources: ["jobs"] verbs: ["create", "get", "list", "watch"]
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check watch permission on jobs
if err := exec.Command("kubectl", "auth", "can-i", "watch", "jobs", "-n", ns).Run(); err != nil {
return fmt.Errorf("serviceaccount cannot watch jobs in namespace %s", ns)
} Try / catch
if err := verifier.Verify(ctx, out, tc); err != nil {
if strings.Contains(err.Error(), "attempting to watch verify job in cluster") {
return fmt.Errorf("job watch failed (add jobs/watch RBAC): %w", err)
}
return err
} Prevention
- Include get/list/watch on batch jobs in the verify ServiceAccount role
- Check API server health before long verify runs
- Use a kubeconfig pointing at the intended cluster/namespace
When it happens
Trigger: clientset.BatchV1().Jobs(ns).Watch(...) returns an error — RBAC denies watch on jobs, namespace doesn't exist, or API server connectivity fails, right after the job was created.
Common situations: ServiceAccount can create but not watch Jobs (missing 'get/watch jobs' RBAC); API server momentarily unavailable; wrong namespace context; network policies blocking watch streams.
Related errors
- attempting to watch verify pods in cluster
- creating verify job in cluster
- initializing deployment watcher
- initializing pod watcher for
- cleaning up deployed job
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/0da88775af503bf1.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/skaffold/verify/k8sjob/verify.go:259
case execErr = <-execCh:
case <-v.timeout(timeoutDuration):
execErr = errors.New(fmt.Sprintf("%q running k8s job timed out after : %v", tc.Name, *timeoutDuration))
v.logger.CancelJobLogger(job.Name)
if err := k8sjobutil.ForceJobDelete(ctx, job.Name, clientset.BatchV1().Jobs(job.Namespace), &v.kubectl); err != nil {
execErr = errors.Wrap(execErr, err.Error())
}
eventV2.VerifyFailed(tc.Name, execErr)
}
return execErr
}
func (v *Verifier) watchJob(ctx context.Context, clientset k8sclient.Interface, job *batchv1.Job, tc latest.VerifyTestCase) error {
w, err := clientset.BatchV1().Jobs(job.Namespace).Watch(ctx,
metav1.ListOptions{FieldSelector: fmt.Sprintf("metadata.name=%s", job.Name)})
if err != nil {
eventV2.VerifyFailed(tc.Name, err)
return errors.Wrap(err, "attempting to watch verify job in cluster")
}
defer w.Stop()
w, err = clientset.CoreV1().Pods(job.Namespace).Watch(ctx,
metav1.ListOptions{
LabelSelector: labels.Set(map[string]string{"job-name": job.Name}).String(),
})
if err != nil {
eventV2.VerifyFailed(tc.Name, err)
return errors.Wrap(err, "attempting to watch verify pods in cluster")
}
defer w.Stop()
var podErr error
for event := range w.ResultChan() {
pod, ok := event.Object.(*corev1.Pod)
if ok {
if pod.Status.Phase == corev1.PodSucceeded {View on GitHub (pinned to a1189de023)