Skip to content

[Start RSC] SerovalUnsupportedTypeError on RawStream during dev SSR — production unaffected #7361

@Vijayabaskar56

Description

@Vijayabaskar56

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions