Link to the code that reproduces this issue
https://github.com/Zefty/nextjs-redirect-bug
To Reproduce
Note this bug only occurs when we enable cache components and run nextjs app in prod.
pnpm build && pnpm start (or deploy to vercel)
- Click the "Settings" button .
- See "Connection closed" error
To fix this error
- Simply disable cache components in config
Current vs. Expected behavior
Current Behaviour
See "Connection closed" error
Expected Behaviour
It should go to /settings -> redirects to /settings/subsettings
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:41:26 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T8132
Available memory (MB): 16384
Available CPU cores: 10
Binaries:
Node: 24.16.0
npm: 11.13.0
Yarn: N/A
pnpm: 10.33.2
Relevant Packages:
next: 16.2.7 // Latest available version is detected (16.2.7).
eslint-config-next: N/A
react: 19.2.4
react-dom: 19.2.4
typescript: 5.9.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
cacheComponents
Which stage(s) are affected? (Select all that apply)
Vercel (Deployed)
Additional context
Notice that in my layout.tsx i have an async component. This is just an example since i don't have auth wired up, but one can expect user details to be fetched and displayed in the layout.
I think this has to do with some incompatibilities with cache components and async calls in layout.tsx since this doesn't happen with cache components being disabled.
AI Analysis
Yes, this looks plausibly like a Next.js bug.
The suspicious path is:
-
redirect() throws NEXT_REDIRECT.
-
For full document renders, Next handles that in next.js/packages/next/src/server/app-render/app-render.tsx:4006 by setting a
redirect status and Location.
-
If streaming has already started, Next relies on
next.js/packages/next/src/server/app-render/make-get-server-inserted-html.tsx:45 to emit <meta id="__next-page-redirect"
...>.
-
But that meta tag is sourced from serverCapturedErrors, which are pushed by the HTML error handler in
next.js/packages/next/src/server/app-render/create-error-handler.tsx:149.
-
Your case has the redirecting page under a parent layout with Suspense + async headers(), so the redirect can be carried
through the RSC/Flight path instead of the HTML error path.
-
On client navigation, Next intentionally returns 200 for RSC redirect requests, per
next.js/test/e2e/app-dir/rsc-redirect/rsc-redirect.test.ts:19. So the client router must handle it.
-
There is a risky catch in next.js/packages/next/src/client/components/segment-cache/navigation.ts:196 that returns the
current state if unknown-route navigation fails. If the redirect escapes as a Flight/RSC error instead of being converted
into a router redirect, the UI can appear to do nothing.
So the likely bug is: a server-component redirect from a page below a suspended async layout is not consistently bridged into
either an HTTP redirect, a streamed refresh meta tag, or a client router redirect during soft navigation/prefetch.
Link to the code that reproduces this issue
https://github.com/Zefty/nextjs-redirect-bug
To Reproduce
Note this bug only occurs when we enable cache components and run nextjs app in prod.
pnpm build && pnpm start(or deploy to vercel)To fix this error
Current vs. Expected behavior
Current Behaviour
See "Connection closed" error
Expected Behaviour
It should go to
/settings-> redirects to/settings/subsettingsProvide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:41:26 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T8132 Available memory (MB): 16384 Available CPU cores: 10 Binaries: Node: 24.16.0 npm: 11.13.0 Yarn: N/A pnpm: 10.33.2 Relevant Packages: next: 16.2.7 // Latest available version is detected (16.2.7). eslint-config-next: N/A react: 19.2.4 react-dom: 19.2.4 typescript: 5.9.3 Next.js Config: output: N/AWhich area(s) are affected? (Select all that apply)
cacheComponents
Which stage(s) are affected? (Select all that apply)
Vercel (Deployed)
Additional context
Notice that in my
layout.tsxi have an async component. This is just an example since i don't have auth wired up, but one can expect user details to be fetched and displayed in the layout.I think this has to do with some incompatibilities with cache components and async calls in layout.tsx since this doesn't happen with cache components being disabled.
AI Analysis
Yes, this looks plausibly like a Next.js bug.
The suspicious path is:
redirect() throws NEXT_REDIRECT.
For full document renders, Next handles that in next.js/packages/next/src/server/app-render/app-render.tsx:4006 by setting a
redirect status and Location.
If streaming has already started, Next relies on
next.js/packages/next/src/server/app-render/make-get-server-inserted-html.tsx:45 to emit <meta id="__next-page-redirect"
...>.
But that meta tag is sourced from serverCapturedErrors, which are pushed by the HTML error handler in
next.js/packages/next/src/server/app-render/create-error-handler.tsx:149.
Your case has the redirecting page under a parent layout with Suspense + async headers(), so the redirect can be carried
through the RSC/Flight path instead of the HTML error path.
On client navigation, Next intentionally returns 200 for RSC redirect requests, per
next.js/test/e2e/app-dir/rsc-redirect/rsc-redirect.test.ts:19. So the client router must handle it.
There is a risky catch in next.js/packages/next/src/client/components/segment-cache/navigation.ts:196 that returns the
current state if unknown-route navigation fails. If the redirect escapes as a Flight/RSC error instead of being converted
into a router redirect, the UI can appear to do nothing.
So the likely bug is: a server-component redirect from a page below a suspended async layout is not consistently bridged into
either an HTTP redirect, a streamed refresh meta tag, or a client router redirect during soft navigation/prefetch.