Error Handling and Retry Logic

This module provides mechanisms to robustly handle errors during data fetching and to implement retry strategies within the SWR (stale-while-revalidate) data fetching paradigm. It integrates React Suspense error boundaries, manual retry interfaces, and configurable automatic retry with exponential backoff to improve resilience and user experience in asynchronous operations.


Core Concepts and Purpose

The Error Handling and Retry Logic module exists to:

This ensures that applications remain responsive and maintain data consistency even if network or server errors occur.


How the Module Works

1. Automatic Error Retry with Exponential Backoff

The module defines a default error retry function, onErrorRetry, which is responsible for scheduling revalidation attempts after an error is encountered during data fetching.

Excerpt from src/_internal/utils/config.ts:

const onErrorRetry = (
  _: unknown,
  __: string,
  config: Readonly<PublicConfiguration>,
  revalidate: Revalidator,
  opts: Required<RevalidatorOptions>
): void => {
  const maxRetryCount = config.errorRetryCount
  const currentRetryCount = opts.retryCount

  // Exponential backoff calculation
  const timeout =
    ~~(
      (Math.random() + 0.5) *
      (1 << (currentRetryCount < 8 ? currentRetryCount : 8))
    ) * config.errorRetryInterval

  if (!isUndefined(maxRetryCount) && currentRetryCount > maxRetryCount) {
    return
  }

  setTimeout(revalidate, timeout, opts)
}

This function is wired into the SWR lifecycle and triggers revalidation attempts according to the retry policy.

2. React Suspense and Error Boundary Integration

Error handling is integrated into React's Suspense model by using error boundaries that catch errors thrown by SWR hooks when data fetching fails.

Example usage in e2e/site/component/manual-retry.tsx:

<ErrorBoundary
  FallbackComponent={Fallback}
  onReset={() => {
    preloadRemote() // preload data on retry reset
  }}
>
  <Suspense fallback={<div>loading</div>}>
    <Demo />
  </Suspense>
</ErrorBoundary>

The Fallback component provides a retry button that calls resetErrorBoundary to reset the error state and allow re-rendering.

3. Manual Retry UI Workflow

In addition to automatic retries, the module supports manual retry triggered by user actions:

Example from e2e/site/component/manual-retry-mutate.tsx:

<button
  onClick={async () => {
    await mutate(key, fetcher) // manually revalidate data
    resetErrorBoundary()       // clear error boundary state
  }}
>
  retry
</button>

This pattern provides a responsive UI that allows users to recover from transient errors by retrying on demand.


Interactions with Other Modules


Design Patterns and Important Concepts


Visualization: Manual Retry with Suspense and Error Boundary Flow

flowchart TD
  A[Component Mounts] --> B[useRemoteData Hook Fetches Data]
  B -->|Fetch Succeeds| F[Render Data]
  B -->|Fetch Fails| C[ErrorBoundary Catches Error]
  C --> D[Fallback UI with Retry Button]
  D -->|User Clicks Retry| E[Trigger SWR mutate to Revalidate]
  E --> B

This flowchart illustrates the lifecycle of data fetching with error handling and manual retry:


Summary of Relevant Files


This module is central to ensuring resilient data fetching by combining automatic retry strategies, declarative error boundaries, and manual retry mechanisms in a cohesive and extensible approach.