# Function withRetry

- withRetry<T>(
  fn: () => Promise<T>,
  options: {
  maxRetries: number;
  maxDelayMs?: number;
  retryDelayMs?: number;
  shouldRetry?: (error: unknown) => boolean;
  timeoutErrorMessage?: string;
  timeoutMs?: number;
  },
  ): Promise<T>

  Execute a function with retry logic and timeout

  Retries the operation up to options.maxRetries times (for a total of maxRetries + 1 attempts including the initial call). Each retry has its own timeout (if timeoutMs is provided).

  By default, all non-TimeoutError failures are considered retryable. To restrict retries to transient failures only (for example, network errors or 5xx status codes), provide a options.shouldRetry predicate that returns true only for errors that should be retried.

  #### Type Parameters

  - T

    Type of the function result

  #### Parameters

  - fn: () => Promise<T>

    Async function to execute

  - options: {
    maxRetries: number;
    maxDelayMs?: number;
    retryDelayMs?: number;
    shouldRetry?: (error: unknown) => boolean;
    timeoutErrorMessage?: string;
    timeoutMs?: number;
    }

    Retry and timeout configuration

    - ##### maxRetries: number

      Maximum number of retry attempts after the initial call

    - ##### `Optional` maxDelayMs?: number

      Maximum delay cap in milliseconds (default: 30000); prevents unbounded backoff growth

    - ##### `Optional` retryDelayMs?: number

      Base delay between retry attempts in milliseconds (default: 1000)

    - ##### `Optional` shouldRetry?: (error: unknown) => boolean

      Predicate that decides if a failed attempt should be retried (default: retry all non-timeout errors)

    - ##### `Optional` timeoutErrorMessage?: string

      Custom error message for timeout errors

    - ##### `Optional` timeoutMs?: number

      Optional per-attempt timeout in milliseconds (omit if fn handles timeout internally)

  #### Returns Promise<T>

  Promise that resolves with the result

  #### Throws

  If any attempt exceeds timeout

  #### Throws

  If all retries are exhausted

  #### Example

      // Retry up to 3 times (4 total attempts) on 5xx errors only with timeout
      const data = await withRetry(
        () => fetchFromAPI('/endpoint'),
        {
          maxRetries: 3,
          timeoutMs: 5000,
          retryDelayMs: 1000,
          shouldRetry: (error) => error.statusCode >= 500
        }
      );

      // Retry without additional timeout (fn handles timeout internally)
      const data2 = await withRetry(
        () => withTimeoutAndAbort(signal => fetch(url, { signal }), 5000),
        {
          maxRetries: 3,
          retryDelayMs: 1000,
          shouldRetry: (error) => error.statusCode >= 500
        }
      );

  #### Security

  - Prevents retry storms with exponential backoff
  - Respects timeout limits per attempt (when provided)
  - Configurable retry conditions for security

  #### Since

  0.8.0

  - Defined in utils/timeout.ts:266