Skip to main content

Error Handling: Data Fetching & Fatal Application Errors

Best Practices Guide for Managing Application Failures


Introduction

In modern web applications, handling errors gracefully is a core requirement. In Archibald, error handling happens on two levels:

  • Data-fetching errors: Failures of individual requests, handled locally through useFetch / useSuspenseFetch options (error, errorBoundary, throwOnError) and React Error Boundaries.
  • Fatal errors: Unrecoverable render errors inside a hydrated island, handled by the Hydrator's built-in ErrorBoundary and its fatalError fallback component.

Fatal errors: the Hydrator's fatalError fallback

Every hydrated island is wrapped in an ErrorBoundary by the Hydrator HOC (withComponentHydration). If a component inside the island throws during render, the boundary catches the error and renders the island's fatal-error fallback instead of crashing the whole page.

  • The fallback is configured via the Hydrator's fatalError prop — a render function receiving FallbackProps (the thrown error and a resetErrorBoundary callback), passed to the boundary as fallbackRender.
  • If you don't provide one, the DefaultFatalErrorComponent from @archibald/storefront is used.
  • Because each island has its own boundary, a fatal error in one island (e.g. the header) does not take down the rest of the page.
const HydratedTeaser = withComponentHydration({
component: Teaser,
fatalError: ({ error, resetErrorBoundary }) => (
<div role="alert">
<p>Something went wrong.</p>
<button onClick={resetErrorBoundary}>Retry</button>
</div>
)
});

Data-fetching errors: useFetch options

For errors that originate from data loading, use the error handling built into the data-fetching hooks — see the error handling deep dive and the per-option pages:

  • error: How long a failed result is kept in the cache (default 500 ms) before a re-attempt is allowed. Tune it so users see the error long enough, without hammering the API.
  • errorBoundary: Set errorBoundary: true (together with suspense: true) to throw fetch errors to the nearest React Error Boundary instead of rendering a half-broken component.
  • throwOnError: Makes the request layer reject on HTTP error status codes so the failure propagates as a real error (per call or globally via config.throwOnError).
  • For non-Suspense usage, branch on the hook's returned isError / error state and render an inline error UI.
<ErrorBoundary fallback={<ErrorMessage />}>
<Suspense fallback={<LoadingSpinner />}>
<UserList /> {/* useFetch(..., { suspense: true, errorBoundary: true }) */}
</Suspense>
</ErrorBoundary>

useNetworkError

Currently non-functional

useNetworkError is intended to detect HTTP error statuses (like 404) from the last network request, but its store integration is currently stubbed out: the last HTTP status is hardcoded to 200, so the hook always returns false. Do not rely on it for 404/error views — handle these cases via useFetch error options or your routing layer instead.

For reference, its intended contract:

  • errorCodes: HTTP status codes to watch for. Defaults to [404].
  • loose: Defaults to true. With loose: true the hook matches when the status is strictly greater than any configured code (status > code), catching whole error ranges with a single entry; with loose: false the status must be contained in errorCodes exactly.

See Also

For a detailed technical breakdown and additional implementation patterns, refer to the following resources:


Key Takeaways

  • Let the Hydrator catch fatal errors: Every island is wrapped in an ErrorBoundary; customize the fallback via the fatalError prop, or rely on DefaultFatalErrorComponent.
  • Handle fetch errors where the data lives: Use useFetch's error / errorBoundary / throwOnError options plus Suspense-aware Error Boundaries for critical data, or the returned isError / error state for inline handling.
  • Don't use useNetworkError: It is currently hardcoded to a 200 status and always returns false.
  • Combine with Logging: When a fatal error is caught, consider logging the error details to a monitoring service (like Sentry) before rendering the error screen.