215 lines
7.8 KiB
Text
215 lines
7.8 KiB
Text
---
|
|
title: Error Handling
|
|
description: Handle runtime errors by automatically wrapping route segments and their nested children in a React Error Boundary.
|
|
---
|
|
|
|
The `error.js` file convention allows you to gracefully handle runtime errors in [nested routes](/docs/app/building-your-application/routing#nested-routes).
|
|
|
|
- Automatically wrap a route segment and its nested children in a [React Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-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:
|
|
|
|
<Image
|
|
alt="error.js special file"
|
|
srcLight="/docs/light/error-special-file.png"
|
|
srcDark="/docs/dark/error-special-file.png"
|
|
width="1600"
|
|
height="606"
|
|
/>
|
|
|
|
```tsx filename="app/dashboard/error.tsx" switcher
|
|
'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>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/dashboard/error.js" switcher
|
|
'use client' // Error components must be Client Components
|
|
|
|
import { useEffect } from 'react'
|
|
|
|
export default function Error({ error, reset }) {
|
|
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
|
|
|
|
<Image
|
|
alt="How error.js works"
|
|
srcLight="/docs/light/error-overview.png"
|
|
srcDark="/docs/dark/error-overview.png"
|
|
width="1600"
|
|
height="903"
|
|
/>
|
|
|
|
- `error.js` automatically creates an [React Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-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.
|
|
|
|
```tsx filename="app/dashboard/error.tsx" switcher
|
|
'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>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/dashboard/error.js" switcher
|
|
'use client'
|
|
|
|
export default function Error({ error, reset }) {
|
|
return (
|
|
<div>
|
|
<h2>Something went wrong!</h2>
|
|
<button onClick={() => reset()}>Try again</button>
|
|
</div>
|
|
)
|
|
}
|
|
```
|
|
|
|
### Nested Routes
|
|
|
|
React components created through [special files](/docs/app/building-your-application/routing#file-conventions) are rendered in a [specific nested hierarchy](/docs/app/building-your-application/routing#component-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:
|
|
|
|
<Image
|
|
alt="Nested Error Component Hierarchy"
|
|
srcLight="/docs/light/nested-error-component-hierarchy.png"
|
|
srcDark="/docs/dark/nested-error-component-hierarchy.png"
|
|
width="1600"
|
|
height="687"
|
|
/>
|
|
|
|
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](#nested-routes) 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.
|
|
|
|
```tsx filename="app/global-error.tsx" switcher
|
|
'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>
|
|
)
|
|
}
|
|
```
|
|
|
|
```jsx filename="app/global-error.js" switcher
|
|
'use client'
|
|
|
|
export default function GlobalError({ error, reset }) {
|
|
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](/docs/app/building-your-application/data-fetching/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.
|