Summary
In Next.js 16's compiled React Flight serializer (next/dist/compiled/next-server/app-page-turbo.runtime.prod.js, the ~318KB outlined-model writer closure), a Symbol.for("react.fragment") value falls through the entire typeof dispatch chain to the tail throw — even though re-evaluating the exact same comparison at the throw site returns true.
Probe installed immediately before the tail throw Error("Type "+typeof a+"..."):
console.error("PRB-TYPE2 recheck="+("symbol"==typeof a)+" strict="+("symbol"===typeof a)+" t="+typeof a+" str="+String(a));
Output under perry (per request):
PRB-TYPE2 recheck=true strict=true t=symbol str=Symbol(react.fragment)
i.e. control passed the function's if("symbol"==typeof a){...} arm without taking it, then the probe — adjacent statements, same variable — sees the comparison as TRUE. The compiled arm evaluated FALSE for the same value the probe sees as a symbol.
Impact
This is the current blocker for Next.js 16 standalone serving (with #6522, #6527, #6537, #6545 and the fetch-super fix applied, the server boots and stays alive): every App Router render 500s with either
Error: Only global symbols received from Symbol.for(...) can be passed to Client Components. The symbol Symbol.for(undefined) cannot be found… or
Error: Type symbol is not supported in Client Component props. (which of the two Flight sites fires varies per build), plus paired Unhandled Rejection: undefined.
What was ruled out (all byte-identical to node in isolation)
Symbol.for/Symbol.keyFor/.description round-trips, incl. cross-module identity (/tmp-style repros).
"symbol"==typeof x dispatch chains on registered/local/well-known symbols in a small function.
- The registry's Box::leak'd symbols pass
js_value_typeof (SYMBOL_POINTERS registry covers non-arena symbols).
The failing function's IR shows the symbol check compiled generically (js_value_typeof + js_string_equals against the interned "symbol"), which is sound — so either the executed check reads a stale/desynced slot for the reassigned minified local a (the function reassigns a heavily; possibly the boxed-vs-direct dual-slot family, cf. #6328/#6345), or codegen emitted a duplicated/specialized variant of the typeof chain (typed-feedback fast path) whose symbol classification diverges, and that variant is the one executing.
Note js_value_typeof returns per-thread cached StringHeaders for its results while the compiled comparison goes through js_string_equals (content compare) — identity vs content shouldn't matter here, but the executed-variant question is open.
Repro
perry compile the gscmaster Next.js 16 standalone app (or any App Router app) at main + PR #6545, boot, curl /<any-page>. The probe text above can be inserted at the single "Type "+typeof a+" is not supported in Client Component props" site in app-page-turbo.runtime.prod.js.
Verified at main 7279998 + #6545 + the fetch-super fix.
Summary
In Next.js 16's compiled React Flight serializer (
next/dist/compiled/next-server/app-page-turbo.runtime.prod.js, the ~318KB outlined-model writer closure), aSymbol.for("react.fragment")value falls through the entire typeof dispatch chain to the tail throw — even though re-evaluating the exact same comparison at the throw site returns true.Probe installed immediately before the tail
throw Error("Type "+typeof a+"..."):Output under perry (per request):
i.e. control passed the function's
if("symbol"==typeof a){...}arm without taking it, then the probe — adjacent statements, same variable — sees the comparison as TRUE. The compiled arm evaluated FALSE for the same value the probe sees as a symbol.Impact
This is the current blocker for Next.js 16 standalone serving (with #6522, #6527, #6537, #6545 and the fetch-super fix applied, the server boots and stays alive): every App Router render 500s with either
Error: Only global symbols received from Symbol.for(...) can be passed to Client Components. The symbol Symbol.for(undefined) cannot be found…orError: Type symbol is not supported in Client Component props.(which of the two Flight sites fires varies per build), plus pairedUnhandled Rejection: undefined.What was ruled out (all byte-identical to node in isolation)
Symbol.for/Symbol.keyFor/.descriptionround-trips, incl. cross-module identity (/tmp-style repros)."symbol"==typeof xdispatch chains on registered/local/well-known symbols in a small function.js_value_typeof(SYMBOL_POINTERS registry covers non-arena symbols).The failing function's IR shows the symbol check compiled generically (
js_value_typeof+js_string_equalsagainst the interned"symbol"), which is sound — so either the executed check reads a stale/desynced slot for the reassigned minified locala(the function reassignsaheavily; possibly the boxed-vs-direct dual-slot family, cf. #6328/#6345), or codegen emitted a duplicated/specialized variant of the typeof chain (typed-feedback fast path) whose symbol classification diverges, and that variant is the one executing.Note
js_value_typeofreturns per-thread cachedStringHeaders for its results while the compiled comparison goes throughjs_string_equals(content compare) — identity vs content shouldn't matter here, but the executed-variant question is open.Repro
perry compilethe gscmaster Next.js 16 standalone app (or any App Router app) at main + PR #6545, boot,curl /<any-page>. The probe text above can be inserted at the single"Type "+typeof a+" is not supported in Client Component props"site in app-page-turbo.runtime.prod.js.Verified at main 7279998 + #6545 + the fetch-super fix.