Skip to main content

unstable_catchError

The unstable_catchError function creates a component that wraps its children in an error boundary. It provides a programmatic alternative to the error.js file convention, enabling component-level error recovery anywhere in your component tree.

Compared to a custom React error boundary, unstable_catchError is designed to work with Next.js out of the box:

  • Built-in error recovery — unstable_retry() re-fetches and re-renders the error boundary's children, including Server Components.
  • Framework-aware integration — APIs like redirect() and notFound() work by throwing special errors under the hood. unstable_catchError handles these seamlessly, so they're not accidentally caught by your error boundary.
  • Client navigation handling — The error state automatically clears when you do a client navigation to a different route.

unstable_catchError can be called from Client Components.

app/custom-error-boundary.tsx
'use client'

import { unstable_catchError, type ErrorInfo } from 'next/error'

function ErrorFallback(
  props: { title: string },
  { error, unstable_retry }: ErrorInfo
) {
  return (
    <div>
      <h2>{props.title}</h2>
      <p>{error.message}</p>
      <button onClick={() => unstable_retry()}>Try again</button>
    </div>
  )
}

export default unstable_catchError(ErrorFallback)
app/custom-error-boundary.js
'use client'

import { unstable_catchError } from 'next/error'

function ErrorFallback(props, { error, unstable_retry }) {
  return (
    <div>
      <h2>{props.title}</h2>
      <p>{error.message}</p>
      <button onClick={() => unstable_retry()}>Try again</button>
    </div>
  )
}

export default unstable_catchError(ErrorFallback)

Reference

Parameters

unstable_catchError accepts a single argument:

const ErrorWrapper = unstable_catchError(fallback)

fallback

A function that renders the error UI when an error is caught. It receives two arguments:

  • props — The props passed to the wrapper component (excluding children).
  • errorInfo — An object containing information about the error:
PropertyTypeDescription
errorErrorThe error instance that was caught.
unstable_retry() => voidRe-fetches and re-renders the error boundary's children. If successful, the fallback is replaced with the re-rendered result.
reset() => voidResets the error state and re-renders without re-fetching. Use unstable_retry() in most cases.

The fallback function must be a Client Component (or defined in a 'use client' module).

Returns

unstable_catchError returns a React component that:

  • Accepts the same props as your fallback's first argument, plus children.
  • Wraps children in an error boundary.
  • Renders the fallback when an error is caught in children.

Examples

Client Component

Define a fallback and use the returned component to wrap parts of your UI:

app/some-component.tsx
import ErrorWrapper from '../custom-error-boundary'

export default function Component({ children }: { children: React.ReactNode }) {
  return <ErrorWrapper title="Dashboard Error">{children}</ErrorWrapper>
}
app/some-component.js
import ErrorWrapper from '../custom-error-boundary'

export default function Component({ children }) {
  return <ErrorWrapper title="Dashboard Error">{children}</ErrorWrapper>
}

Recovering from errors

Use unstable_retry() to prompt the user to recover from the error. When called, the function re-fetches and re-renders the error boundary's children. If successful, the fallback is replaced with the re-rendered result.

In most cases, use unstable_retry() instead of reset(). The reset() function only clears the error state and re-renders without re-fetching, which means it won't recover from Server Component errors.

app/custom-error-boundary.tsx
'use client'

import { unstable_catchError, type ErrorInfo } from 'next/error'

function ErrorFallback(props: {}, { error, unstable_retry, reset }: ErrorInfo) {
  return (
    <div>
      <p>{error.message}</p>
      <button onClick={() => unstable_retry()}>Try again</button>
      <button onClick={() => reset()}>Reset</button>
    </div>
  )
}

export default unstable_catchError(ErrorFallback)
app/custom-error-boundary.js
'use client'

import { unstable_catchError } from 'next/error'

function ErrorFallback(props, { error, unstable_retry, reset }) {
  return (
    <div>
      <p>{error.message}</p>
      <button onClick={() => unstable_retry()}>Try again</button>
      <button onClick={() => reset()}>Reset</button>
    </div>
  )
}

export default unstable_catchError(ErrorFallback)

Server-rendered error fallback

You can pass server-rendered content as a prop to display data-driven fallback UI. This works by rendering a Server Component as a React.ReactNode prop that the fallback displays when an error is caught.

Good to know

This pattern eagerly renders the fallback on every page render, even when no error occurs. For most use cases, a simpler client-side fallback is sufficient.

app/error-boundary.tsx
'use client'

import { unstable_catchError, type ErrorInfo } from 'next/error'

function ErrorFallback(
  props: { fallback: React.ReactNode },
  errorInfo: ErrorInfo
) {
  return props.fallback
}

export default unstable_catchError(ErrorFallback)
app/error-boundary.js
'use client'

import { unstable_catchError } from 'next/error'

function ErrorFallback(props, errorInfo) {
  return props.fallback
}

export default unstable_catchError(ErrorFallback)
app/some-component.tsx
import ErrorBoundary from '../error-boundary'

async function ErrorFallback() {
  const data = await getData()
  return <div>{data.message}</div>
}

export default function Component({ children }: { children: React.ReactNode }) {
  return <ErrorBoundary fallback={<ErrorFallback />}>{children}</ErrorBoundary>
}
app/some-component.js
import ErrorBoundary from '../error-boundary'

async function ErrorFallback() {
  const data = await getData()
  return <div>{data.message}</div>
}

export default function Component({ children }) {
  return <ErrorBoundary fallback={<ErrorFallback />}>{children}</ErrorBoundary>
}

Good to know

  • Unlike the error.js file convention which is scoped to route segments, unstable_catchError can be used to wrap any part of your component tree for component-level error recovery.
  • Props passed to the wrapper component are forwarded to the fallback function, making it easy to create reusable error UIs with different configurations.
  • You don't need to wrap error.js default exports with unstable_catchError. The error.js file convention already renders inside a built-in error boundary provided by Next.js.

Version History

VersionChanges
v16.2.0unstable_catchError introduced.