Courses
Next.js
Error Handling

Error Handling

The error.js file convention allows you to gracefully handle unexpected 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 application 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:

    • layout.js
      • layout.js
      • page.js
      • error.js
  • 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

    • 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.

    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 inside a Server Component, Next.js will forward an Error object (stripped of sensitive error information in production) to the nearest error.js file as the error prop.

    Securing Sensitive Error Information

    During production, the Error object forwarded to the client only includes a generic message and digest property.

    This is a security precaution to avoid leaking potentially sensitive details included in the error to the client.

    The message property contains a generic message about the error and the digest property contains an automatically generated hash of the error that can be used to match the corresponding error in server-side logs.

    During development, the Error object forwarded to the client will be serialized and include the message of the original error for easier debugging.