#99287·Next.js

notFound() serves an empty `__next_error__` document instead of not-found.tsx

Author: franknoelCreated Sep 26, 2026Updated Sep 28, 2026
LabelsError HandlingNot Found

Link to the code that reproduces this issue

https://github.com/franknoel/next-notfound-ssr

To Reproduce

  1. Clone the reproduction and run npm install.
  2. Run npm run build && npm run start (npm run dev shows the same thing).
  3. Run ./check.sh, or fetch the pages by hand:
bash
curl -s http://localhost:3000/missing        # page that calls notFound()
curl -s http://localhost:3000/no/such/route  # URL that matches no route

The app has three files: a root layout with <html lang="en">, an app/not-found.tsx that renders NOT FOUND BOUNDARY, and app/[slug]/page.tsx, which calls notFound() unless the slug is known.

Current vs. Expected behavior

Current: /missing answers 404, but its HTML is <html id="__next_error__"><head></head><body> plus scripts. The root layout does not render, so there is no lang and none of the not-found.tsx markup. That markup exists only in the RSC payload, so the page is blank until it hydrates, and stays blank without JavaScript.

An unmatched URL (/no/such/route) is fine: it renders not-found.tsx inside the root layout.

check.sh output, the same on 16.3.6 and 16.4.0-canary.48, in next dev and in next build && next start:

/known           200  <html lang="en">             boundary/page text in HTML: yes
/missing         404  <html id="__next_error__">   boundary/page text in HTML: no
/no/such/route   404  <html lang="en">             boundary/page text in HTML: yes

Expected: /missing renders like /no/such/route: the root layout with NOT FOUND BOUNDARY in the server HTML, and the same 404 status.

Provide environment information

bash
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.6.0: Tue Aug 18 17:49:13 PDT 2026; root:xnu-12377.161.15.700.19~2/RELEASE_ARM64_T6000
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 24.21.0
  npm: 11.19.0
  Yarn: 1.22.22
  pnpm: 9.15.9
Relevant Packages:
  next: 16.3.6 // Latest available version is detected (16.3.6).
  eslint-config-next: N/A
  react: 19.2.8
  react-dom: 19.2.8
  typescript: 5.9.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not Found, Error Handling

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local), next start (local), Vercel (Deployed)

Additional context

Also reproduces on [email protected], dev and prod.

Same bug as #98295 and #98954, which were closed automatically for lacking a reproduction link.

Where it seems to happen: HTTPAccessFallbackBoundary is a client error boundary, and React does not run error boundaries during server rendering, so the notFound() throw escapes the Fizz shell. The catch in app-render (renderToStream, and prerenderToStream for ISR) sets the 404 status and renders getErrorRSCPayload, whose seed is the hardcoded __next_error__ document. Because the status and the empty document come from the same catch, an app cannot get a 404 with real HTML from notFound().

We hit it on a site with locale-prefixed routes: every unknown page and event URL is served without lang or any text.