Next.js 16 /_not-found Prerender Build Error: The Real Fix
Next.js 16 build crashes prerendering the internal /_not-found route. Here are the three actual causes behind it, how to tell which one is yours, and the fix for each.
If you upgraded to Next.js 16 and your production build now dies with something like:
Error occurred prerendering page "/_not-found"you're not looking at a config typo. You're looking at one of three distinct regressions that all surface through the same internal route, because /_not-found is the one page every App Router build always tries to prerender — even if you never touch it. That makes it the canary for a handful of unrelated Next.js 16 problems.
This is the diagnostic path that actually separates the three causes, based on the confirmed GitHub reports (vercel/next.js#85604, #86978, #84994) and what's changed since Next.js 15.
Why /_not-found breaks even though you never wrote code for it#
The App Router auto-generates a /_not-found route from your root not-found.js/layout.js tree. Next.js prerenders it as a static fallback during next build, which means any import anywhere in your root layout — even three levels deep in a dependency — gets pulled into that prerender pass. In Next.js 15 this was forgiving. In Next.js 16, prerendering got stricter about what's allowed to run without a request context, and about what a Server Component is allowed to pass to a Client Component. /_not-found is where that strictness first bites, because it has to render with zero real request.
Cause 1 — a function is being passed to a Client Component#
The most common variant, matching #85604: your build log says
Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server"This happens when something in your root layout — often a <Link> wrapper, an analytics provider, or a custom error boundary — passes a callback prop (an onClick, a formatter function, a render-prop) from a Server Component into a Client Component that also gets rendered on the /_not-found path. Next.js 15 silently serialized this in some cases; Next.js 16 rejects it outright, as confirmed by the Next.js team on this exact build failure.
Fix: find the component tree your root layout.js renders unconditionally (headers, providers, global nav) and audit every prop passed into a 'use client' boundary. Any function prop needs to either move inside the Client Component itself, or be wrapped as a Server Action with 'use server' if it genuinely needs to run server-side. For the same message outside /_not-found, including how to read the caret line that names the offending prop, see Functions cannot be passed directly to Client Components.
Cause 2 — workUnitAsyncStorage invariant under Turbopack#
If your error instead reads:
Error [InvariantError]: Invariant: Expected workUnitAsyncStorage to have a store(seen in #86978 on Next.js 16.0.8 + Turbopack), the cause is a dependency calling headers(), cookies(), or draftMode() unconditionally at module scope or during prerendering, with no request context available. One confirmed repro in that thread traced this to react-instantsearch-nextjs calling headers() on the server with no guard. Because /_not-found prerenders with no real request, any library that assumes a request always exists will throw here first.
Fix: audit third-party packages that touch Next.js server APIs (search widgets, i18n libraries, analytics SDKs) for calls to headers()/cookies() that aren't wrapped in try/catch or gated behind connection(). Pin the dependency to a version predating the offending change, or move the call behind a component that only renders on genuinely dynamic routes — never in the root layout that /_not-found inherits.
Cause 3 — pageExtensions or custom route config touching the internal route#
A smaller number of reports (#65447 and older) trace back to a custom pageExtensions array in next.config.mjs that inadvertently matches internal Next.js files, causing the framework's own _not-found implementation to be shadowed or double-resolved. If your error trace mentions pageExtensions or a resolution conflict rather than a runtime crash, check that config first — it's the cheapest cause to rule out.
How to tell which one is yours in under 5 minutes#
- Run
next buildwith--debugif available, or read the full stack trace above the "Error occurred prerendering page /_not-found" line — the real error is always printed just before it. - "Functions cannot be passed directly to Client Components" → Cause 1.
- "workUnitAsyncStorage" or "InvariantError" → Cause 2.
- Anything mentioning
pageExtensionsor route resolution → Cause 3. - If none of those match, bisect: temporarily strip your root
layout.jsdown to a bare<html><body>{children}</body></html>and rebuild. If the build passes, reintroduce providers one at a time until it breaks again.
Prevention going forward#
Treat your root layout as prerender-critical code, not just app chrome. Every provider or wrapper you add there runs during the /_not-found prerender whether you like it or not. If you're also migrating cache behavior at the same time, read Next.js 16 "use cache" errors: why your Cache Components break — the two upgrades often get tackled in the same PR and the failure modes can look similar in the build log.
Why your nested not-found.js isn't the one crashing the build#
A common assumption while debugging this error is that a project's nested
app/blog/[slug]/not-found.js is the file being prerendered, so people spend time
auditing it and find nothing wrong. That's usually the wrong file to look at.
When notFound() is called (or a route genuinely doesn't match) inside a segment,
the App Router renders the nearest not-found.js up the route tree from that
segment — not necessarily the one you just wrote. If app/blog/[slug]/ has no
not-found.js of its own, the lookup keeps climbing until it reaches the root
app/not-found.js, or Next.js's own internal default if your project has none at
all. That root-level fallback is exactly the /_not-found route this whole error
class prerenders, which is why the crash happens even in projects whose nested
not-found pages are completely fine — the nested file was never in the render path
for the case that fails.
This matters for diagnosis: if you're bisecting per the steps above and stripping
providers out of layout.js doesn't help, check whether a nested segment's
not-found.js is even being reached at all, or whether every 404 in your app is
quietly falling through to the root one. A missing nested not-found.js is not a
bug by itself — it's the documented default behavior — but it does mean the root
layout's full provider tree (and every module-scope side effect inside it) renders
on every 404 across the entire app, not just ones you expected to hit the root.
If your project defines route groups — app/(marketing)/not-found.js alongside
app/(dashboard)/not-found.js — each group's not-found.js only covers routes
inside that group; a 404 outside any group still falls through to the true root.
Confirming which not-found.js actually renders for a given URL, and how that
interacts with route groups and parallel routes, is exactly the kind of App Router
routing detail covered in
Next.js Pages Router to App Router migration guide —
worth a read before assuming the nested file you wrote is the one Next.js is
actually prerendering during the build failure.
Further reading: Next.js Build Passed But Production Broke. Also see Fix Export encountered errors on following paths in Next.js.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
Continue Reading
Fix Next.js missing .next/BUILD_ID at server startup
Separate an absent build from the wrong application root, a mismatched output folder and development artifacts, using the file the production server checks.
Fix: sh: 1: next: not found on Heroku
Three different, unrelated situations produce the exact same Heroku crash — here is how to tell which one is yours before you change anything.
Fix Export encountered errors on following paths in Next.js
Read the path list as a map back to your own code: /about/undefined, /components/Navbar and /about/[slug] each point at a different bug, rebuilt on Next.js 16.4.2 (and the first on 14.2.35 too).


