argoproj/argo-workflows · error
failed to get retry strategy: %w
Error message
failed to get retry strategy: %w
What it means
runEmissary parses the retry strategy from the workflow template (template.GetRetryStrategy) to build a retry.OnError backoff before executing the command. This error means the template's retryStrategy could not be decoded/validated — typically the embedded template JSON in /var/run/argo/template is malformed or carries an invalid retryStrategy (e.g. bad duration).
Source
Thrown at cmd/argoexec/commands/emissary.go:225
}
name, err = exec.LookPath(name)
if err != nil {
return fmt.Errorf("failed to find name in PATH: %w", err)
}
if os.Getenv("ARGO_DEBUG_PAUSE_BEFORE") == "true" {
// User can create the file: /ctr/NAME_OF_THE_CONTAINER/before
// in order to break out of the wait and release the container from
// the debugging state.
if waitErr := file.WaitForCreate(ctx, varRunArgo+"/ctr/"+containerName+"/before"); waitErr != nil {
return fmt.Errorf("failed waiting for debug-pause-before marker: %w", waitErr)
}
}
backoff, err := template.GetRetryStrategy()
if err != nil {
return fmt.Errorf("failed to get retry strategy: %w", err)
}
cmdErr := retry.OnError(backoff, func(error) bool { return true }, func() error {
command, closer, err := startCommand(ctx, name, args, template, containerName, includeScriptOutput)
if err != nil {
return fmt.Errorf("failed to start command: %w", err)
}
defer closer()
forwardSignals(ctx, signals, command.Process.Pid, false)
pid := command.Process.Pid
innerCtx, cancel := context.WithCancel(ctx)
defer cancel()
startFileSignalHandler(innerCtx, pid, containerName)
for _, sidecarName := range template.GetSidecarNames() {
if sidecarName == containerName {
em, err := emissary.New()
if err != nil {View on GitHub (pinned to 35bff19146)
Solutions
- Fix the workflow's retryStrategy fields (valid duration like "30s", positive limits) and resubmit
- Ensure the argoexec image version matches the workflow-controller version
- Check the content of /var/run/argo/template in the pod for corruption
- If only default behavior is needed, remove retryStrategy from the template
Example fix
// before
retryStrategy:
limit: "abc"
// after
retryStrategy:
limit: "3"
backoff:
duration: "30s" Defensive patterns
Strategy: validation
Validate before calling
// client-side lint before submit
const wf = yaml.parse(manifest);
for (const t of allTemplates(wf)) {
const rs = t.retryStrategy;
if (rs && rs.limit && !/^[0-9]+$/.test(String(rs.limit))) throw new Error(`retryStrategy.limit must be an integer: ${rs.limit}`);
if (rs && rs.backoff && rs.backoff.duration && isNaN(Date.parse('1970-01-01T00:00:' + rs.backoff.duration))) throw new Error('bad duration: ' + rs.backoff.duration);
} Try / catch
try { await submit(wf) } catch (e) { if (/failed to get retry strategy/.test(e.message)) { runArgoLint(wf); } throw e } Prevention
- Run `argo lint` on every workflow manifest before submit (validate shares the same parsing)
- Pin argoexec and controller to the same release version
- Use canonical retryStrategy fields (integer limit, duration like "30s")
- Never hand-edit the serialized template blob under /var/run/argo
When it happens
Trigger: template.GetRetryStrategy returns an error: the retryStrategy fields in the workflow template fail validation/unmarshaling (invalid duration format, wrong types), or the /var/run/argo/template blob passed to argoexec is corrupt/truncated.
Common situations: A workflow with retryStrategy whose duration/value is out of range or malformed; running an argoexec image whose API version mismatches the controller (template serialization changed); hand-edited or corrupted template ConfigMap/downward API content.
Related errors
- duration has to be positive, current duration: %v
- template '%s' type is unknown
- cron schedules must consist of 5 values only
- ${e.Usage()}
- --completed and --running cannot be used together
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/3af2b0dfb5a3bf34.
Report an issue: GitHub.