[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, Exclude<E, AbortError>>,
  __namedParameters?: RetryOptions<Exclude<E, AbortError>, Output>,
): Task<T, RetryTaskError<E>, D>;
```

Defined in: [packages/common/src/Task.ts:3979](https://github.com/evoluhq/evolu/blob/037c390af081e9944d616ff298a729515c5c5ab7/packages/common/src/Task.ts#L3979)

Retries a [Task](https://evolu.dev/docs/api-reference/common/Task/type-aliases/Task) according to a [Schedule](https://evolu.dev/docs/api-reference/common/Schedule/type-aliases/Schedule).

Use `retry` for failure recovery: it repeats after [Err](https://evolu.dev/docs/api-reference/common/Result/interfaces/Err) and wraps the
final domain error. Use [repeat](https://evolu.dev/docs/api-reference/common/Task/functions/repeat) for success-driven loops: it repeats
after [Ok](https://evolu.dev/docs/api-reference/common/Result/interfaces/Ok) and returns the Task's natural [Result](https://evolu.dev/docs/api-reference/common/Result/type-aliases/Result).

[AbortError](https://evolu.dev/docs/api-reference/common/Task/variables/AbortError) passes through unchanged when returned as a Result error,
such as from [daemon](https://evolu.dev/docs/api-reference/common/Task/functions/daemon). Abort from `run(task)` remains [Fiber](https://evolu.dev/docs/api-reference/common/Task/interfaces/Fiber)
control flow. Other errors are domain errors: retrying continues while the
schedule yields another delay and [RetryOptions.shouldRetry](https://evolu.dev/docs/api-reference/common/Task/interfaces/RetryOptions#shouldretry) returns
`true`. When retrying stops, `retry` returns [RetryError](https://evolu.dev/docs/api-reference/common/Task/interfaces/RetryError) with the final
domain error as `lastError`.

AbortError recognition is structural. Domain errors, especially values parsed
from untrusted input, must not use the reserved AbortError shape.

### Retrying failures

```ts
import {
  assertErr,
  assertType,
  createRun,
  err,
  recurs,
  retry,
  type Result,
  type RetryTaskError,
  type Task,
  type Typed,
} from "@evolu/common";

const fetchData: Task<string, ServiceUnavailableError> = () =>
  err({ type: "ServiceUnavailable" });

interface ServiceUnavailableError extends Typed<"ServiceUnavailable"> {}

const fetchWithRetry = retry(fetchData, recurs(2));

await using run = createRun();
const result = await run(fetchWithRetry);
assertType<
  Result<string, RetryTaskError<ServiceUnavailableError>>,
  typeof result
>();
assertErr(result, {
  type: "RetryError",
  attempts: 3,
  lastError: { type: "ServiceUnavailable" },
});
```

### Filtering retries

```ts
import {
  assertErr,
  createRun,
  err,
  recurs,
  retry,
  type Task,
  type Typed,
} from "@evolu/common";

const fetchData: Task<
  string,
  TemporaryFailureError | PermanentFailureError
> = () => err({ type: "PermanentFailure" });

interface TemporaryFailureError extends Typed<"TemporaryFailure"> {}

interface PermanentFailureError extends Typed<"PermanentFailure"> {}

const fetchWithRetry = retry(fetchData, recurs(5), {
  shouldRetry: (error) => error.type !== "PermanentFailure",
});

await using run = createRun();
const result = await run(fetchWithRetry);
assertErr(result, {
  type: "RetryError",
  attempts: 1,
  lastError: { type: "PermanentFailure" },
});
```