Skip to content

Errors and Retries

A failed step can be retried. Configure it through StepConfig.retries on flow.do and the other activity APIs: false to disable, a number, a duration string, or a RetryStrategy with limit, delay, and backoff.

Two conditions for this to be useful. The step has to be safe to run twice, and it has to have a stable name — otherwise the second attempt looks like different work and the event history stops making sense.

A retry does not make an external call happen exactly once. Nothing does. See below.

NonRetryableError says “don’t try again”. ValidationError is not retried unless you explicitly pass retryable: true — the default assumes bad input stays bad.

Exact names and shapes: Workflow API.

When a workflow calls out to another system, that call is delivered at least once. It can arrive twice.

This is not a limitation waiting to be fixed; it’s the honest answer for anything crossing a process boundary. The consequence is concrete: whatever you call needs to accept an idempotency key, or some other stable identity for the request, and treat a repeat as a no-op.

The receiving system’s acknowledgement is what counts. The workflow records that it reached the boundary — not that the other side did the work.

Before deciding whether to retry, read the instance state and its events in order. Usually the answer is visible there.

Do not repair a run by editing or deleting the stream. And keep provider payloads and credentials out of whatever you save: a good error report names the workflow, the step, who was acting, and a stable error code, and contains no parameters and no secrets.

The Workflow Test error is a worked example of exactly that shape. For restart behaviour, see Restart and resume.