ErrorState
The page threw.
Why it exists
Next's default error boundary is an unstyled black-on-white page reading “Application error: a client-side exception has occurred”. No brand, no theme, no reference, and nothing an operator can do with it.
What it looks like
Root's says which database is probably down; Ivy's says what to search the logs for; Hana's logs the digest and says nothing. All three console.error in a useEffect, all three render a reset button, all three decide their own page padding.
Root could not render this page
Usually its database is unreachable. The deployments already queued are unaffected — they live in Postgres, not in this page.
reference 4f2a91c7The whole boundary, in four lines
PageError is the file: it does the console.error nobody remembers, and it is the reason an app with no boundary can get one without deciding anything.
The console.error is inside PageError rather than left to the caller because it is the part that gets forgotten — and without it a client-side exception leaves no trace anywhere at all: the server never saw it, and the boundary swallowed it.
Print the reference; do not print the message
In production React replaces the exception message with a hash before it reaches the browser. That hash is the only thing connecting what the user saw to the line in the server log.
error.message is empty in production
In both themes
light
Something failed
The server failed while rendering this page. One retry is worth trying; if it keeps happening, the reference below is what to search the logs for.
reference 4f2a91c7dark
Something failed
The server failed while rendering this page. One retry is worth trying; if it keeps happening, the reference below is what to search the logs for.
reference 4f2a91c7Guidance
Use it when
- app/error.tsx in every app. Seven of the twelve still have none.
- A title naming the app and what failed — “Ivy could not load this run”, not “Error”.
- A body saying what is unaffected. That sentence is what stops someone escalating, and only the app can write it.
Reach for something else when
- “Something went wrong.” True of every failure and useful for none.
- Rendering error.message. Empty in production, stack-shaped in development.
- A retry with no way out. If the failure is a bad record, retrying loads it again — pair onRetry with an action that leaves.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | — | What failed, from this app's point of view. |
| children | ReactNode | — | What it means and what is unaffected. The sentence only the app can write. |
| error | { digest?: string } | — | React's error. The digest is printed; the message deliberately is not. |
| onRetry | () => void | — | Next's reset. Renders the retry button when given. |
| action | ReactNode | — | A way out that is not a retry — “Back to runs”. |
| PageError scope | string | — | Prefixes the console line, so the log says which app it came from. |
Related
EmptyState is the other half of this pair: one is a list with nothing in it, the other is a page that could not be built. Both follow the same rule — say why, and say what would change it. A bare “No data” and a bare “Something went wrong” are the same mistake, and they are indistinguishable from each other to the person reading them.