Skip to content
    App Router...RoutingError Handling

    Error Handling

    The error.js file convention allows you to gracefully handle runtime errors in nested routes.

    • Automatically wrap a route segment and its nested children in a React Error Boundary.
    • Create error UI tailored to specific segments using the file-system hierarchy to adjust granularity.
    • Isolate errors to affected segments while keeping the rest of the app functional.
    • Add functionality to attempt to recover from an error without a full page reload.

    Create error UI by adding an error.js file inside a route segment and exporting a React component:

    error.js special file
    app/dashboard/error.tsx
    'use client'; // Error components must be Client Components
     
    import { useEffect } from 'react';
     
    export default function Error({
      error,
      reset,
    }: {
      error: Error;
      reset: () => void;
    }) {
      useEffect(() => {
        // Log the error to an error reporting service
        console.error(error);
      }, [error]);
     
      return (
        <div>
          <h2>Something went wrong!</h2>
          <button
            onClick={
              // Attempt to recover by trying to re-render the segment
              () => reset()
            }
          >
            Try again
          </button>
        </div>
      );
    }

    How error.js Works

    How error.js works
    • error.js automatically creates an React Error Boundary that wraps a nested child segment or page.js component.
    • The React component exported from the error.js file is used as the fallback component.
    • If an error is thrown within the error boundary, the error is contained, and the fallback component is rendered.
    • When the fallback error component is active, layouts above the error boundary maintain their state and remain interactive, and the error component can display functionality to recover from the error.

    Recovering From Errors

    The cause of an error can sometimes be temporary. In these cases, simply trying again might resolve the issue.

    An error component can use the reset() function to prompt the user to attempt to recover from the error. When executed, the function will try to re-render the Error boundary's contents. If successful, the fallback error component is replaced with the result of the re-render.

    app/dashboard/error.tsx
    'use client';
     
    export default function Error({
      error,
      reset,
    }: {
      error: Error;
      reset: () => void;
    }) {
      return (
        <div>
          <h2>Something went wrong!</h2>
          <button onClick={() => reset()}>Try again</button>
        </div>
      );
    }

    Nested Routes

    React components created through special files are rendered in a specific nested hierarchy.

    For example, a nested route with two segments that both include layout.js and error.js files are rendered in the following simplified component hierarchy:

    Nested Error Component Hierarchy

    The nested component hierarchy has implications for the behavior of error.js files across a nested route:

    • Errors bubble up to the nearest parent error boundary. This means an error.js file will handle errors for all its nested child segments. More or less granular error UI can be achieved by placing error.js files at different levels in the nested folders of a route.
    • An error.js boundary will not handle errors thrown in a layout.js component in the same segment because the error boundary is nested inside that layouts component.

    Handling Errors in Layouts

    error.js boundaries do not catch errors thrown in layout.js or template.js components of the same segment. This intentional hierarchy keeps important UI that is shared between sibling routes (such as navigation) visible and functional when an error occurs.

    To handle errors within a specific layout or template, place an error.js file in the layouts parent segment.

    To handle errors within the root layout or template, use a variation of error.js called global-error.js.

    Handling Errors in Root Layouts

    The root app/error.js boundary does not catch errors thrown in the root app/layout.js or app/template.js component.

    To specifically handle errors in these root components, use a variation of error.js called app/global-error.js located in the root app directory.

    Unlike the root error.js, the global-error.js error boundary wraps the entire application, and its fallback component replaces the root layout when active. Because of this, it is important to note that global-error.js must define its own <html> and <body> tags.

    global-error.js is the least granular error UI and can be considered "catch-all" error handling for the whole application. It is unlikely to be triggered often as root components are typically less dynamic, and other error.js boundaries will catch most errors.

    Even if a global-error.js is defined, it is still recommended to define a root error.js whose fallback component will be rendered within the root layout, which includes globally shared UI and branding.

    app/global-error.tsx
    'use client';
     
    export default function GlobalError({
      error,
      reset,
    }: {
      error: Error;
      reset: () => void;
    }) {
      return (
        <html>
          <body>
            <h2>Something went wrong!</h2>
            <button onClick={() => reset()}>Try again</button>
          </body>
        </html>
      );
    }

    Handling Server Errors

    If an error is thrown during data fetching or inside a Server Component, Next.js will forward the resulting Error object to the nearest error.js file as the error prop.

    When running next dev, the error will be serialized and forwarded from the Server Component to the client error.js. To ensure security when running next start in production, a generic error message is forwarded to error along with a .digest which contains a hash of the error message. This hash can be used to correspond to server logs.

    Was this helpful?