Which project does this relate to?
Start
Describe the bug
@tanstack/react-start/rscloaders that return values fromcreateCompositeComponent(...)` crash during dev-mode SSR dehydration. Production builds are unaffected — same code, same route, dev throws, prod renders.
Server log
Serialization error: SerovalUnsupportedTypeError: The value [object Object] of type "object" cannot be parsed/serialized.
value: RawStream { stream: ReadableStream, hint: 'text' }
at parseObjectPhase2 (seroval/src/core/context/sync-parser.ts:743)
at parseObject (seroval/src/core/context/sync-parser.ts:773)
at parseSOS (seroval/src/core/context/sync-parser.ts:815)
at StreamParsePluginContext.parse (seroval/src/core/context/sync-parser.ts:150)
at Object.stream (router-core/src/ssr/serializer/transformer.ts:193)
Client console
Invariant failed: Expected to find a dehydrated data on window.$\_TSR.router, but we did not. Please file an issue!
at hydrate (ssr-client.js:31)
at hydrateStart (hydrateStart.js:27)
Dehydration aborts mid-write, so window.$_TSR.router never reaches the client and hydrate() throws on load.
Root cause
Vite dev runs each environment (client, ssr, rsc, nitro) through a separate module-runner, so the RawStream class at packages/router-core/src/ssr/serializer/RawStream.ts is loaded once per env with distinct constructor identities.
packages/react-start-rsc/src/serialization.server.ts:183 constructs new RawStream(stream, { hint: 'text' }) in the RSC env. RawStreamSSRPlugin.test() at packages/router-core/src/ssr/serializer/RawStream.ts:323-325 runs in a different env and evaluates value instanceof RawStream — which returns false cross-realm. The plugin doesn't claim the value, the seroval parser falls through, parseObjectPhase2 throws SerovalUnsupportedTypeError at seroval/src/core/context/sync-parser.ts:743. The same instanceof pattern at RawStream.ts:407 in createRawStreamRPCPlugin has the same flaw.
Production Rollup deduplicates everything into a single bundle per target → one RawStream constructor → instanceof works → no crash.
I've validated locally with a bun patch @tanstack/router-core@1.169.2 that swaps instanceof RawStream for a Symbol.for('@tanstack/router.RawStream') brand check (and adds the brand in the constructor). With the patch, both /rsc-test and complex RSC routes start working in dev with zero seroval errors. Production behavior is unchanged. PR with the fix at #.
Complete minimal reproducer
https://github.com/timelessco/reform
Steps to Reproduce the Bug
Branch: main. The route src/routes/rsc-test.tsx is the docs createCompositeComponent example pattern verbatim — see Server Components docs → Composite (slots). It reproduces directly after bun install && bun dev.
1. `git clone https://github.com/timelessco/reform && cd reform`
2. `bun install` (or `pnpm install` / `npm install`)
3. `bun dev`
4. Open `http://localhost:3000/rsc-test`
Observed:
- Server terminal logs `SerovalUnsupportedTypeError: ... value: RawStream { stream: ReadableStream, hint: 'text' }` from `transformer.ts:193`.
- Browser console throws `Invariant failed: Expected to find a dehydrated data on window.$_TSR.router`.
- The page renders the dev-server error overlay instead of the RSC test fixture.
For comparison, the same route on the deployed Vercel build renders correctly:
https://better-forms-mu.vercel.app/rsc-test
The route source — identical to the docs example, ~50 LOC:
https://github.com/timelessco/reform/blob/main/src/routes/rsc-test.tsx
Expected behavior
I expected /rsc-test to render in dev exactly the way it renders in production: the loader return is dehydrated, the RSC payload streams, the client hydrates without error.
Instead, dev-mode SSR aborts dehydration mid-write because Vite's per-environment module-runner causes value instanceof RawStream in RawStreamSSRPlugin.test to return false, so the plugin doesn't claim the value and seroval throws.
Screenshots or Videos
No response
Platform
- Router / Start Version: @tanstack/react-start 1.167.64, @tanstack/react-router 1.169.2, @tanstack/router-core 1.169.2, @tanstack/router-plugin 1.167.34
- OS: macOS 25.3.0 (Darwin)
- Browser: Chrome
- Browser Version: latest
- Bundler: vite (with @vitejs/plugin-rsc 0.5.24, @vitejs/plugin-react 5.2.0)
- Bundler Version: 7.3.1
Additional context
I have patch the package that you give addtional context and for me that actuall resolved the issues, here is the pr link for reference : timelessco/reform#73
Which project does this relate to?
Start
Describe the bug
@tanstack/react-start/rsc
loaders that return values fromcreateCompositeComponent(...)` crash during dev-mode SSR dehydration. Production builds are unaffected — same code, same route, dev throws, prod renders.Server log
Client console
Dehydration aborts mid-write, so
window.$_TSR.routernever reaches the client andhydrate()throws on load.Root cause
Vite dev runs each environment (
client,ssr,rsc,nitro) through a separate module-runner, so theRawStreamclass atpackages/router-core/src/ssr/serializer/RawStream.tsis loaded once per env with distinct constructor identities.packages/react-start-rsc/src/serialization.server.ts:183constructsnew RawStream(stream, { hint: 'text' })in the RSC env.RawStreamSSRPlugin.test()atpackages/router-core/src/ssr/serializer/RawStream.ts:323-325runs in a different env and evaluatesvalue instanceof RawStream— which returnsfalsecross-realm. The plugin doesn't claim the value, the seroval parser falls through,parseObjectPhase2throwsSerovalUnsupportedTypeErroratseroval/src/core/context/sync-parser.ts:743. The sameinstanceofpattern atRawStream.ts:407increateRawStreamRPCPluginhas the same flaw.Production Rollup deduplicates everything into a single bundle per target → one
RawStreamconstructor →instanceofworks → no crash.I've validated locally with a
bun patch @tanstack/router-core@1.169.2that swapsinstanceof RawStreamfor aSymbol.for('@tanstack/router.RawStream')brand check (and adds the brand in the constructor). With the patch, both/rsc-testand complex RSC routes start working in dev with zero seroval errors. Production behavior is unchanged. PR with the fix at #.Complete minimal reproducer
https://github.com/timelessco/reform
Steps to Reproduce the Bug
Expected behavior
I expected
/rsc-testto render in dev exactly the way it renders in production: the loader return is dehydrated, the RSC payload streams, the client hydrates without error.Instead, dev-mode SSR aborts dehydration mid-write because Vite's per-environment module-runner causes
value instanceof RawStreaminRawStreamSSRPlugin.testto returnfalse, so the plugin doesn't claim the value and seroval throws.Screenshots or Videos
No response
Platform
Additional context
I have patch the package that you give addtional context and for me that actuall resolved the issues, here is the pr link for reference : timelessco/reform#73