argoproj/argo-workflows · error

failed to get retry strategy

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).

Solutions

  1. Fix the workflow's retryStrategy fields (valid duration like "30s", positive limits) and resubmit
  2. Ensure the argoexec image version matches the workflow-controller version
  3. Check the content of /var/run/argo/template in the pod for corruption
  4. 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

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


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/3af2b0dfb5a3bf34. Report an issue: GitHub.

Appendix: 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)