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
- Upgrade skaffold to the latest version so its k8s.io/api library knows the phase your cluster reports
- Pin/downgrade the cluster or use a standard Kubernetes distribution if a nonstandard phase is being emitted
- Inspect the reported phase value and file an issue if it's a legit new Kubernetes phase
- 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
- Keep skaffold and its k8s.io/api dependency current relative to your cluster version
- Use standard Kubernetes distributions that emit standard PodPhase values
- Fix test fakes to emit valid corev1.PodPhase constants
- Track Kubernetes release notes for new pod phases before upgrading clusters
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
- pod has failed
- STATUSCHECK_POD_INITIALIZING
- waiting for init container %s to complete
- STATUSCHECK_UNKNOWN
- STATUSCHECK_CONTAINER_TERMINATED
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/61d94be5bc4dfdd6.
Report an issue: GitHub.