helm/helm · error

expected %s to be a *v1.Pod, got %T

Error message

expected %s to be a *v1.Pod, got %T

What it means

Internal invariant failure in legacyWaiter.waitForPodSuccess (pkg/kube/wait.go:324). The watcher routed an event object as a Pod (Kind 'Pod'), but it did not decode to *corev1.Pod, so the type assertion fails. Like the Job variant, it indicates kind/type confusion in the watch stream rather than a workload problem.

Source

Thrown at pkg/kube/wait.go:324

		if c.Type == batchv1.JobComplete && c.Status == "True" {
			return true, nil
		} else if c.Type == batchv1.JobFailed && c.Status == "True" {
			slog.Error("job failed", "job", name, "reason", c.Reason)
			return true, fmt.Errorf("job %s failed: %s", name, c.Reason)
		}
	}

	slog.Debug("job status update", "job", name, "active", o.Status.Active, "failed", o.Status.Failed, "succeeded", o.Status.Succeeded)
	return false, nil
}

// waitForPodSuccess is a helper that waits for a pod to complete.
//
// This operates on an event returned from a watcher.
func (hw *legacyWaiter) waitForPodSuccess(obj runtime.Object, name string) (bool, error) {
	o, ok := obj.(*corev1.Pod)
	if !ok {
		return true, fmt.Errorf("expected %s to be a *v1.Pod, got %T", name, obj)
	}

	switch o.Status.Phase {
	case corev1.PodSucceeded:
		slog.Debug("pod succeeded", "pod", o.Name)
		return true, nil
	case corev1.PodFailed:
		slog.Error("pod failed", "pod", o.Name)
		return true, fmt.Errorf("pod %s failed", o.Name)
	case corev1.PodPending:
		slog.Debug("pod pending", "pod", o.Name)
	case corev1.PodRunning:
		slog.Debug("pod running", "pod", o.Name)
	case corev1.PodUnknown:
		slog.Debug("pod unknown", "pod", o.Name)
	}

	return false, nil

View on GitHub (pinned to 2a29f1770b)

Solutions

  1. Check for CRDs whose kind is 'Pod' (kubectl get crds) and rename them.
  2. Clear the discovery/cache and retry after cluster upgrades settle.
  3. Prefer the status-watcher wait path (GroupKind-based) in SDK code instead of the legacy Pod watcher.
Defensive patterns

Strategy: type-guard

Type guard

func isCorePod(obj runtime.Object) bool {
	_, ok := obj.(*corev1.Pod)
	return ok
}

Try / catch

if err != nil && strings.Contains(err.Error(), "to be a *v1.Pod") {
	// kind/type confusion: check CRDs named Pod, refresh discovery, retry
}

Prevention

When it happens

Trigger: Rare: requires an event identified as a Pod that decodes to another Go type — custom CRD with kind 'Pod', schema/discovery cache mismatch after cluster or Helm upgrades, or a serializer picking the wrong registered type.

Common situations: CRDs shadowing core 'Pod' kind; stale client-side discovery caches; mid-upgrade control planes serving inconsistent schemas.

Related errors


AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15). Data as JSON: /api/errors/45d2aee45cacb580. Report an issue: GitHub.