GoogleContainerTools/skaffold · error

unknown phase: %s

Error message

unknown phase: %s

What it means

The pod watcher received a pod whose Status.Phase is not one of Succeeded, Failed, Unknown, or Pending — the isPodSucceeded predicate treats any other phase as an unknown enum value and errors with 'unknown phase: %s'. This guards against newer Kubernetes phase values the running code doesn't understand.

Source

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

		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) {
		if event.Object == nil {
			return false, nil
		}

View on GitHub (pinned to a1189de023)

Solutions

  1. Upgrade skaffold to the latest version so its k8s.io/api library knows the phase your cluster reports
  2. Pin/downgrade the cluster or use a standard Kubernetes distribution if a nonstandard phase is being emitted
  3. Inspect the reported phase value and file an issue if it's a legit new Kubernetes phase
  4. If it comes from a test fake, fix the fake to emit valid corev1.PodPhase values

Example fix

// before: k8s client lib too old for cluster phase
// after
// upgrade dependency:
go get k8s.io/api@latest k8s.io/client-go@latest
go build ./...
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure only known phases reach the wait predicate
func knownPhase(p corev1.Pod) bool {
    switch p.Status.Phase {
    case corev1.PodSucceeded, corev1.PodFailed, corev1.PodUnknown, corev1.PodPending, corev1.PodRunning:
        return true
    }
    return false
}

Type guard

func isKnownPodPhase(p *corev1.Pod) bool {
    switch p.Status.Phase {
    case corev1.PodPending, corev1.PodRunning, corev1.PodSucceeded, corev1.PodFailed, corev1.PodUnknown:
        return true
    default:
        return false
    }
}

Try / catch

err := kubernetes.WaitForPodSucceeded(ctx, pods, podName, timeout)
if err != nil && strings.HasPrefix(err.Error(), "unknown phase") {
    log.Printf("cluster reported a phase this skaffold doesn't know; upgrade skaffold: %v", err)
}

Prevention

When it happens

Trigger: During WaitForPodSucceeded's watch, an event delivers a pod whose phase string (e.g. a phase introduced by a newer API server or an unusual distribution) doesn't match any known v1.Pod constant handled in the switch.

Common situations: Skaffold binary built against an older k8s.io/api version talking to a newer cluster that reports a phase constant unknown to it; running against a non-standard Kubernetes-compatible distribution; a mocked/fake client emitting a bogus phase.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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