[API reference](https://evolu.dev/docs/api-reference) › [@evolu/common](https://evolu.dev/docs/api-reference/common) › [Task](https://evolu.dev/docs/api-reference/common/Task) › retry

```ts
function retry<T, E, D, Output>(
  task: Task<T, E, D>,
  schedule: Schedule<Output, E>,
  __namedParameters?: RetryOptions<E, Output>,
): Task<T, RetryError<E>, D>;
```

Defined in: [packages/common/src/Task.ts:2013](https://github.com/evoluhq/evolu/blob/e7144e2bbe9069362b62dec1b64a8aa922b8f1b0/packages/common/src/Task.ts#L2013)

Wraps a [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task) with retry logic.

Retries the Task according to the [Schedule](https://evolu.dev/docs/api-reference/common/Schedule/type-aliases/Schedule)'s rules. Use
[RetryOptions.retryable](https://evolu.dev/docs/api-reference/common/Task/interfaces/RetryOptions#retryable) to filter which errors should trigger retries.

All non-abort errors are wrapped in [RetryError](https://evolu.dev/docs/api-reference/common/Task/interfaces/RetryError):

- Task succeeds → `ok(value)`
- Task returns [AbortError](https://evolu.dev/docs/api-reference/common/Task/variables/AbortError) → `err(AbortError)` — passed through, no
  retry, no wrapping
- Task returns any other error → retry until schedule exhausted or `retryable`
  returns false → `err(RetryError)` with `cause` = the last error

The `RetryError` is informative: "I tried N times, here's why I finally gave
up" — and `cause` contains the actual underlying error.

### Example

```ts

const fetchWithRetry = retry(
  fetchData,
  // A jittered, capped, limited exponential backoff.
  jitter(1)(maxDelay("20s")(take(2)(exponential("100ms")))),
);

const result = await run(fetchWithRetry);
if (!result.ok) {
  if (AbortError.is(result.error)) {
    // Was aborted externally
  } else {
    // RetryError — failed after retrying
    console.log(`Failed after ${result.error.attempts} attempts`);
    console.log(`Last error:`, result.error.cause);
  }
}
```

The schedule receives the error as input, enabling error-aware strategies
like stopping on fatal errors:

```ts

// Don't retry fatal errors
const smartRetry = retry(
  fetchData,
  whileScheduleInput((e: FetchError) => e.type !== "FatalError")(
    take(5)(spaced("1s")),
  ),
);
```

## See

[RetryOptions](https://evolu.dev/docs/api-reference/common/Task/interfaces/RetryOptions)