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

  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.