GoogleContainerTools/skaffold · error

pod has failed

Error message

pod has failed

What it means

During pod wait, the callback inspects pod.Status.Phase and immediately fails the wait with "pod has failed" when the phase is PodFailed. It is used by deploy status checks that wait for a pod to reach Succeeded/Running and abort early on failure.

Source

Thrown at pkg/skaffold/kubernetes/wait.go:94

	return func(event *watch.Event) (bool, error) {
		if event.Object == nil {
			return false, nil
		}
		pod, isPod := event.Object.(*v1.Pod)
		if !isPod {
			return false, nil
		}
		if pod.Name != podName {
			return false, nil
		}

		switch pod.Status.Phase {
		case v1.PodSucceeded:
			return true, nil
		case v1.PodRunning:
			return false, nil
		case v1.PodFailed:
			return false, errors.New("pod has failed")
		case v1.PodUnknown, v1.PodPending:
			return false, nil
		}
		return false, fmt.Errorf("unknown phase: %s", pod.Status.Phase)
	}
}

// WaitForPodInitialized waits until init containers have started running
func WaitForPodInitialized(ctx context.Context, pods corev1.PodInterface, podName string) error {
	log.Entry(ctx).Infof("Waiting for %s to be initialized", podName)

	w, err := newPodsWatcher(ctx, pods)
	if err != nil {
		return fmt.Errorf("initializing pod watcher: %s", err)
	}
	defer w.Stop()

	return watchUntilTimeout(ctx, 10*time.Minute, w, func(event *watch.Event) (bool, error) {

View on GitHub (pinned to a1189de023)

Solutions

  1. Run `kubectl describe pod <pod>` and check containerStatuses/state.exitCode for the failure reason
  2. Fix the container command/entrypoint or the application error causing the nonzero exit
  3. Check init containers and volumes (missing ConfigMaps/Secrets also fail pods) and re-run the deploy

Example fix

// before
command: ["/app/run.sh"]
// after
command: ["/bin/sh", "-c", "chmod +x /app/run.sh && /app/run.sh"]  # fix failing entrypoint
Defensive patterns

Strategy: try-catch

Validate before calling

// before waiting, verify pod spec sanity
if pod.Spec.RestartPolicy == v1.RestartPolicyNever && isJobLike(pod) { /* failure = non-zero exit, handle explicitly */ }

Type guard

func podFailed(pod *v1.Pod) bool { return pod.Status.Phase == v1.PodFailed }

Try / catch

done, err := waitFn(pod)
if err != nil && podFailed(pod) {
  reason := firstContainerTerminationReason(pod) // e.g. Error, OOMKilled
  return fmt.Errorf("pod %s failed (reason=%s): %w", pod.Name, reason, err)
}

Prevention

When it happens

Trigger: Waiting on a pod whose status transitions to v1.PodFailed (container exited nonzero, failed init container, failed scheduler/eviction reporting Failure phase).

Common situations: Test pods or Jobs whose containers exit with a nonzero code; nodes evicting pods; images with bad entrypoints so the main container immediately dies.

Related errors


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