{"record":{"id":"45d2aee45cacb580","repo":"helm/helm","slug":"expected-s-to-be-a-v1-pod-got-t","errorCode":null,"errorMessage":"expected %s to be a *v1.Pod, got %T","messagePattern":"expected (.+?) to be a \\*v1\\.Pod, got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/kube/wait.go","lineNumber":324,"sourceCode":"\t\tif c.Type == batchv1.JobComplete && c.Status == \"True\" {\n\t\t\treturn true, nil\n\t\t} else if c.Type == batchv1.JobFailed && c.Status == \"True\" {\n\t\t\tslog.Error(\"job failed\", \"job\", name, \"reason\", c.Reason)\n\t\t\treturn true, fmt.Errorf(\"job %s failed: %s\", name, c.Reason)\n\t\t}\n\t}\n\n\tslog.Debug(\"job status update\", \"job\", name, \"active\", o.Status.Active, \"failed\", o.Status.Failed, \"succeeded\", o.Status.Succeeded)\n\treturn false, nil\n}\n\n// waitForPodSuccess is a helper that waits for a pod to complete.\n//\n// This operates on an event returned from a watcher.\nfunc (hw *legacyWaiter) waitForPodSuccess(obj runtime.Object, name string) (bool, error) {\n\to, ok := obj.(*corev1.Pod)\n\tif !ok {\n\t\treturn true, fmt.Errorf(\"expected %s to be a *v1.Pod, got %T\", name, obj)\n\t}\n\n\tswitch o.Status.Phase {\n\tcase corev1.PodSucceeded:\n\t\tslog.Debug(\"pod succeeded\", \"pod\", o.Name)\n\t\treturn true, nil\n\tcase corev1.PodFailed:\n\t\tslog.Error(\"pod failed\", \"pod\", o.Name)\n\t\treturn true, fmt.Errorf(\"pod %s failed\", o.Name)\n\tcase corev1.PodPending:\n\t\tslog.Debug(\"pod pending\", \"pod\", o.Name)\n\tcase corev1.PodRunning:\n\t\tslog.Debug(\"pod running\", \"pod\", o.Name)\n\tcase corev1.PodUnknown:\n\t\tslog.Debug(\"pod unknown\", \"pod\", o.Name)\n\t}\n\n\treturn false, nil","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/helm/helm/blob/2a29f1770b62844b27197d2507377361d45ad7c0/pkg/kube/wait.go#L306-L342","documentation":"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.","triggerScenarios":"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.","commonSituations":"CRDs shadowing core 'Pod' kind; stale client-side discovery caches; mid-upgrade control planes serving inconsistent schemas.","solutions":["Check for CRDs whose kind is 'Pod' (kubectl get crds) and rename them.","Clear the discovery/cache and retry after cluster upgrades settle.","Prefer the status-watcher wait path (GroupKind-based) in SDK code instead of the legacy Pod watcher."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isCorePod(obj runtime.Object) bool {\n\t_, ok := obj.(*corev1.Pod)\n\treturn ok\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"to be a *v1.Pod\") {\n\t// kind/type confusion: check CRDs named Pod, refresh discovery, retry\n}","preventionTips":["Avoid CRD kinds that shadow core Pod.","Re-run after discovery caches refresh post-upgrade."],"tags":["kubernetes","type-assertion","wait","crd","invariant"],"backgroundTag":null,"analyzedSha":"2a29f1770b62844b27197d2507377361d45ad7c0","analyzedAt":"2026-08-15T22:02:47.490Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}