argoproj/argo-workflows · error
Error applying PodSpecPatch
Error message
Error applying PodSpecPatch
What it means
After building the pod spec, the controller applies any podSpecPatch(es) with util.ApplyPodSpecPatch. If the resulting JSON/strategic-merge patch is invalid or cannot be applied to the generated pod spec, the build fails with this wrapped error.
Source
Thrown at workflow/controller/workflowpod.go:744
}
}
return nil
})
if err != nil {
return nil, err
}
// Apply the patch string from workflow and template
var podSpecPatchs []string
podSpecPatchs, err = pb.processPodSpecPatch(ctx, tmpl, pod)
if err != nil {
return nil, err
}
if len(podSpecPatchs) > 0 {
var patchedPodSpec *apiv1.PodSpec
patchedPodSpec, err = util.ApplyPodSpecPatch(pod.Spec, podSpecPatchs...)
if err != nil {
return nil, errors.Wrap(err, "", "Error applying PodSpecPatch")
}
pod.Spec = *patchedPodSpec
}
// In init-less mode the emissary binary is mounted at /argo-bin via the
// argoexec-bin image volume, not copied to /var/run/argo by an init container.
// K8s image volumes expose the image's root filesystem as-is.
argoexecBinaryPath := pb.layout.argoexecBinaryPath()
for i, c := range pod.Spec.Containers {
if !common.IsArgoSidecar(c.Name) {
// https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#notes
if len(c.Command) == 0 {
var x *entrypoint.Image
x, err = pb.deps.lookupImage(ctx, c.Image, entrypoint.Options{
Namespace: pb.in.namespace, ServiceAccountName: pb.in.execWfSpec.ServiceAccountName, ImagePullSecrets: pb.in.execWfSpec.ImagePullSecrets,
})
if err != nil {
return nil, fmt.Errorf("failed to look-up entrypoint/cmd for image %q, you must either explicitly specify the command, or list the image's command in the index: https://argo-workflows.readthedocs.io/en/latest/workflow-executors/#emissary-emissary: %w", c.Image, err)View on GitHub (pinned to 35bff19146)
Solutions
- Validate the patch JSON syntax and patch operations
- Ensure patched container names match generated containers ('main', 'init', 'wait')
- Print the generated pod (kubectl get pod -o yaml) and align the patch with its structure
Example fix
// before
podSpecPatch: '[{"op":"replace","path":"/containers/1/image","value":"foo"}]' // container 1 may not exist
// after
podSpecPatch: '[{"op":"replace","path":"/containers/0/image","value":"foo"}]' Defensive patterns
Strategy: validation
Validate before calling
// validate patch JSON before applying
var check interface{}
if err := json.Unmarshal([]byte(patchStr), &check); err != nil {
return fmt.Errorf("invalid podSpecPatch JSON: %w", err)
} Try / catch
patched, err := util.ApplyPodSpecPatch(pod.Spec, patches...)
if err != nil {
return nil, fmt.Errorf("error applying PodSpecPatch: %w", err)
}
pod.Spec = *patched Prevention
- Use correct container names ('main') in patches
- Validate JSON/strategic-merge patch syntax offline (kubectl patch --dry-run)
- Inspect generated pods and keep patches aligned with the spec structure
When it happens
Trigger: podSpecPatch with invalid JSON, patching a container name that doesn't exist (e.g. not 'main'), or a patch incompatible with the generated pod spec structure.
Common situations: Hand-written JSON patches with wrong container names; strategic-merge patches that conflict with injected volumes/volumes mounts; multi-patch templates (with pod_spec_patch as output parameter) producing incompatible patches at runtime.
Related errors
- Failed to substitute the PodSpecPatch variables
- failed to read container args file %s: %w
- failed to unmarshal container args: %w
- failed to read template: %w
- failed to start command: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/cec7a3400b859781.
Report an issue: GitHub.