Restate handles retries for failed invocations.
Check out the Error Handling guide to learn more about how Restate handles transient errors, terminal errors, retries, and timeouts.

Retry strategies

By default, Restate does infinite retries with an exponential backoff strategy. Check out the error handling guide to learn how to customize this.

Terminal errors

For failures for which you do not want retries, but instead want the invocation to end and the error message to be propagated back to the caller, you can throw a terminal error. You can throw a TerminalError with an HTTP status code and structured metadata anywhere in your handler:
The message, code, and metadata are recorded with the failure and propagated to callers. Catch TerminalError to inspect them and build your control flow around the failure:
Terminal error metadata requires Restate Server 1.6 or newer. Metadata keys and values must be strings.
When you throw a terminal error, you might need to undo the actions you did earlier in your handler to make sure that your system remains in a consistent state. Have a look at our sagas guide to learn more.

Retryable errors with custom delay

Use RetryableError to signal that Restate should retry with a specific delay. This is useful when interacting with external APIs that return a Retry-After header. RetryableError is primarily designed for use inside ctx.run blocks:
You can also wrap an existing error using the RetryableError.from helper:
Unlike TerminalError which stops retries permanently, RetryableError tells Restate to retry after the specified delay. You can combine it with maxRetryAttempts and maxRetryDuration in the run options.

Pausing invocations

PauseError and onJournalMismatchErrors require Restate Server 1.7 with RESTATE_EXPERIMENTAL_ENABLE_PROTOCOL_V7=true enabled.
A paused invocation stops retrying until you resume it. This is useful when an operator must fix the underlying problem before another attempt can succeed.

Pause from a durable step

Throw PauseError from a ctx.run closure to pause the invocation. If you throw it outside ctx.run, Restate ignores the pause request and applies the normal invocation retry policy.
After you fix the configuration and resume the invocation, Restate retries the ctx.run closure.

Handle journal mismatch errors

A journal mismatch happens when replayed code produces different Restate operations from the original execution. By default, Restate applies the invocation retry policy. Set onJournalMismatchErrors on a service or handler to choose another outcome.

Mapping errors to TerminalError

If you’re using external libraries (e.g., for validation), you might want to automatically convert certain error types into terminal errors. You can do this using the asTerminalError option in your service configuration. For example, to fail with TerminalError for each MyValidationError, do the following: