argoproj/argo-workflows · error
-1
-1
Error message
Could not find wait container in pod spec
What it means
GetWaitContainerIndex scans pod.Spec.Containers for the Argo 'wait' container and returns -1 with this error when none is found. Every legacy workflow pod must include the wait sidecar, which performs artifact/output capture; its absence means the pod is not a valid Argo workflow pod for the legacy layout.
Source
Thrown at workflow/util/util.go:1749
return false
}
if platform, keyExists := nodeSelector["kubernetes.io/os"]; keyExists && platform == "windows" {
return true
}
return false
}
func FindWaitCtrIndex(pod *apiv1.Pod) (int, error) {
waitCtrIndex := -1
for i, ctr := range pod.Spec.Containers {
if ctr.Name == common.WaitContainerName {
waitCtrIndex = i
}
}
if waitCtrIndex == -1 {
err := errors.Errorf("-1", "Could not find wait container in pod spec")
return -1, err
}
return waitCtrIndex, nil
}
// FindAuxiliaryCtrIndex returns the index of the auxiliary executor container
// on the pod — wait in the legacy layout, supervisor in the init-less layout.
// Returns -1 and an error if neither is found.
func FindAuxiliaryCtrIndex(pod *apiv1.Pod) (int, error) {
for i, ctr := range pod.Spec.Containers {
if ctr.Name == common.WaitContainerName || ctr.Name == common.SupervisorContainerName {
return i, nil
}
}
return -1, errors.Errorf("-1", "Could not find wait or supervisor container in pod spec")
}
View on GitHub (pinned to 35bff19146)
Solutions
- If running the init-less/emissary runtime, use FindAuxiliaryCtrIndex instead, which matches both wait and supervisor containers
- Verify the workflow pod template still includes common.WaitContainerName in spec.containers
- Check whether an admission webhook or security policy is removing containers from workflow pods
- Ensure you are not inspecting a non-workflow pod (plain k8s pod without Argo executor setup)
Example fix
// before idx, err := util.GetWaitContainerIndex(pod) // after (works for both legacy and init-less pods) idx, err := util.FindAuxiliaryCtrIndex(pod)
Defensive patterns
Strategy: validation
Validate before calling
func hasWaitContainer(pod *apiv1.Pod) bool {
for _, c := range pod.Spec.Containers {
if c.Name == common.WaitContainerName {
return true
}
}
return false
} Type guard
func isLegacyWorkflowPod(pod *apiv1.Pod) bool {
_, found := pod.Labels[common.LabelKeyWorkflow]
return found && hasWaitContainer(pod)
} Try / catch
idx, err := util.GetWaitContainerIndex(pod)
if err != nil {
// fall back to init-less layout
if idx2, err2 := util.FindAuxiliaryCtrIndex(pod); err2 == nil {
idx = idx2
} else {
return fmt.Errorf("no executor container in pod %s: %w", pod.Name, err)
}
} Prevention
- Use FindAuxiliaryCtrIndex to cover both legacy and init-less pods
- Check controller container-runtime executor config (emissary vs legacy) before inspecting pods
- Audit admission webhooks for container stripping
- Verify pod is a workflow pod via labels before indexing containers
When it happens
Trigger: Calling GetWaitContainerIndex on a pod built without the wait container: init-less (emissary/supervisor) pods that lack the legacy wait sidecar, hand-edited pod specs, pods whose wait container was removed by a mutating webhook or admission policy.
Common situations: Running with the init-less/supervisor container runtime (SOCKS5/emissary mode) while code still expects the legacy wait container; cluster policies (e.g. Istio sidecar injection policies or security controllers) stripping containers; users manually editing generated pod manifests.
Related errors
- failed to create dependency dir: %w
- dependency %q exited with non-zero code: %d
- watching supervisor status: %w
- supervisor presumed dead: status marker never appeared withi
- stat supervisor status: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/3e584155eaccb9fa.
Report an issue: GitHub.