Fix Node.js streams: remove waitForAllReady from prerenderToStream#92843
Fix Node.js streams: remove waitForAllReady from prerenderToStream#92843mmastrac wants to merge 1 commit into
Conversation
The prerenderToStream legacy path was passing { waitForAllReady: true }
to renderFizzStream, which was added in #92513. With Node.js streams
enabled, renderToNodeFizzStream defers pipeable.pipe() to onAllReady,
but the pipeable was already being piped by an earlier callback, causing
React to throw "only supports piping to one writable stream".
The web stream path ignores this option (it's a no-op), which is why
the bug only manifests with __NEXT_USE_NODE_STREAMS=true.
Remove { waitForAllReady: true } from both the main and error Fizz
render calls in prerenderToStream. The prerender path already handles
stream completion separately.
Fixes production builds failing on /_not-found when the root layout
wraps children in <Suspense>.
Failing test suitesCommit: 3639b6a | About building and testing Next.js
Expand output● rewrites manual href/as › production mode › should allow manual href/as on index page
Expand output● app-dir - metadata-static-generation › should contain async generated metadata in head for simple static page ● app-dir - metadata-static-generation › should contain async generated metadata in head static page with suspenseful content
Expand output● app-dir - metadata-streaming-static-generation › static pages (production) › should contain async generated metadata in head for simple static page ● app-dir - metadata-streaming-static-generation › static pages (production) › should contain async generated metadata in head for slow static page ● app-dir - metadata-streaming-static-generation › static pages (production) › should contain async generated metadata in head static page with suspenseful content |
Stats from current PR✅ No significant changes detected📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📝 Changed Files (8 files)Files with changes:
View diffsapp-page-exp..ntime.dev.jsfailed to diffapp-page-exp..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsfailed to diffapp-page-tur..time.prod.jsDiff too large to display app-page-tur..ntime.dev.jsDiff too large to display app-page-tur..time.prod.jsDiff too large to display app-page.runtime.dev.jsDiff too large to display app-page.runtime.prod.jsDiff too large to display 📎 Tarball URL |
What
Remove
{ waitForAllReady: true }from the tworenderFizzStreamcalls inprerenderToStream's legacy path.Why
PR #92513 added
{ waitForAllReady: true }to these Fizz render calls when switching them fromrenderToWebFizzStreamto the conditionalrenderFizzStream. With__NEXT_USE_NODE_STREAMS=true,renderToNodeFizzStreamdeferspipeable.pipe()toonAllReady, but the pipeable was already piped, causing React to throw:The web stream path ignores
waitForAllReady(the parameter is_options), which is why this only manifests with Node.js streams enabled.The prerender path already handles stream completion separately, so
waitForAllReadyis unnecessary here.Reproduction
Fails with "React currently only supports piping to one writable stream" on
/_not-foundprerender. Any app with a root layout that wraps children in<Suspense>is affected.Test plan
metadata-suspensetest passes with__NEXT_USE_NODE_STREAMS=truemissing-suspense-with-csr-bailout"should pass build" test passes with__NEXT_USE_NODE_STREAMS=true__NEXT_USE_NODE_STREAMS