notFound
API Reference for the notFound function.
The notFound function throws an error that renders a Next.js 404 page. It's useful for handling missing resources in your application. You can customize the UI using the not-found.js file.
Invoking notFound() throws a NEXT_HTTP_ERROR_FALLBACK;404 error and terminates rendering of the route segment where it was thrown. Next.js also injects a <meta name="robots" content="noindex" /> tag so the page is not indexed. Because it works by throwing, call it in the render path: a component, or a function a component awaits. A call left in an un-awaited promise throws where nothing catches it, and no not-found UI renders (in development the server logs ⨯ unhandledRejection: NEXT_HTTP_ERROR_FALLBACK;404).
notFound() can be invoked in Server Components, Server Functions, and Route Handlers.
Good to know
You do not need to write return notFound(). Calling it is enough, because it throws an exception that stops function execution. TypeScript understands this from its never return type, so a value you check first stays narrowed afterward:
Like any exception, it travels up the call stack until something catches it. A try/catch around the call suppresses it, and the not-found UI won't render. If you need to catch errors near the call, use unstable_rethrow to let the interrupt through first.
Examples
Calling notFound() after streaming has started
To keep a page's shell and loading UI visible while data loads, do the existence check inside a component wrapped in <Suspense> instead of blocking the whole route. The idiomatic place for the check is the data-access function itself, awaited by the component that needs the data:
When the post doesn't exist, getPost calls notFound(), which throws. Because this happens during rendering, the exception propagates to the nearest not-found boundary, which renders in place of the streamed-in content, even though the page shell has already been sent.
Add a not-found.tsx alongside the route to define that UI. Without one, the nearest parent not-found boundary renders, falling back to Next.js's default 404 page:
The trade-off is the HTTP status code. Because the check runs inside the <Suspense> boundary, the response has already begun streaming as a 200, and the status can't change once streaming has started. The noindex tag keeps a soft 404 out of search results. To return a real 404 status, the resource has to be checked before the response streams. With Cache Components, every dynamic route streams a static shell first, so run that check in proxy instead. See Status codes.
Serving a 404 from a Route Handler
notFound() also works in a Route Handler, where it serves a 404 to the caller.
Version History
| Version | Changes |
|---|---|
v13.0.0 | notFound introduced. |