Describe the bug
Summary
On StackBlitz (WebContainer / Node 22), the initial vite:anonymous:auth call throws and the dev server crashes. DevTools never connects.
The handler in vite:anonymous:auth is declared jsonSerializable: true. When it throws, birpc wraps the rejection into { id, e: <Error> } and the WS transport runs strictJsonStringify on the whole envelope, which then fails with DF0020 because e is an Error. The original DTK0011 is lost and the process exits.
Environment
- StackBlitz WebContainer, Node `v22.22.0`, Vite `8.0.12`
- `@vitejs/devtools@0.1.21`, `devframe@0.1.21/0.1.22`, `birpc@4.0.0`
Log
> playground@0.0.1 dev /home/projects/pariqzvbqw.github/playground
> vite dev
(node:131) ExperimentalWarning: WASI is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:131) ExperimentalWarning: WASI is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:131) ExperimentalWarning: WASI is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
VITE v8.0.12 ready in 2653 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
ℹ Websocket client connected. [0] [undefined] (untrusted)
[DTK0011] RPC error on executing "vite:anonymous:auth"
╰▶ see: https://devtools.vite.dev/errors/dtk0011
[DF0020] RPC function "vite:anonymous:auth" declares `jsonSerializable: true` but the value at "e" is a Error.
├▶ hint: Either drop `jsonSerializable: true` (falls back to structured-clone) or change the value to a JSON-safe shape.
╰▶ see: https://devfra.me/errors/df0020
[DTK0012] RPC error on executing rpc
╰▶ see: https://devtools.vite.dev/errors/dtk0012
CodedError: [DF0020] RPC function "vite:anonymous:auth" declares `jsonSerializable: true` but the value at "e" is a Error.
at new CodedError (file:///home/projects/pariqzvbqw.github/node_modules/.pnpm/logs-sdk@0.0.6/node_modules/logs-sdk/dist/index.mjs:92:3)
at Object.throw (file:///home/projects/pariqzvbqw.github/node_modules/.pnpm/logs-sdk@0.0.6/node_modules/logs-sdk/dist/index.mjs:141:10)
at nonJsonAt (file:///home/projects/pariqzvbqw.github/node_modules/.pnpm/devframe@0.1.22_typescript@6.0.3/node_modules/devframe/dist/serialization-CwO31axa.mjs:121:10)
at Object.strictReplacer (file:///home/projects/pariqzvbqw.github/node_modules/.pnpm/devframe@0.1.22_typescript@6.0.3/node_modules/devframe/dist/serialization-CwO31axa.mjs:110:60)
at Module.strictJsonStringify (file:///home/projects/pariqzvbqw.github/node_modules/.pnpm/devframe@0.1.22_typescript@6.0.3/node_modules/devframe/dist/serialization-CwO31axa.mjs:95:14)
at eval (file:///home/projects/pariqzvbqw.github/node_modules/.pnpm/devframe@0.1.22_typescript@6.0.3/node_modules/devframe/dist/rpc/transports/ws-server.mjs:64:108)
at onMessage (file:///home/projects/pariqzvbqw.github/node_modules/.pnpm/birpc@4.0.0/node_modules/birpc/dist/index.mjs:207:17) {
diagnostic: {
code: 'DF0020',
level: 'error',
message: 'RPC function "vite:anonymous:auth" declares `jsonSerializable: true` but the value at "e" is a Error.',
docs: 'https://devfra.me/errors/df0020',
hint: 'Either drop `jsonSerializable: true` (falls back to structured-clone) or change the value to a JSON-safe shape.'
}
}
Node.js v22.22.0
ELIFECYCLE Command failed with exit code 1.
ELIFECYCLE Command failed with exit code 1.
Suggested fix (by Claude Code)
jsonSerializable: true is a contract about the result, not about thrown errors. The error slot (e) should not be passed through strictJsonStringify; coerce it to { name, message, stack } or use structured-clone serialization regardless of the flag.
This also makes the underlying handler failure (DTK0011) visible instead of masked by DF0020.
Reproduction
https://stackblitz.com/github/baseballyama/vite-devtools-svelte
System Info
System:
OS: macOS 26.3
CPU: (12) arm64 Apple M4 Pro
Memory: 111.70 MB / 48.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.13.0 - /Users/baseballyama/.nodenv/versions/24.13.0/bin/node
npm: 11.12.1 - /Users/baseballyama/.nodenv/versions/24.13.0/bin/npm
pnpm: 10.25.0 - /Users/baseballyama/.nodenv/versions/24.13.0/bin/pnpm
bun: 1.3.11 - /opt/homebrew/bin/bun
Deno: 2.5.6 - /opt/homebrew/bin/deno
Used Package Manager
pnpm
Validations
Describe the bug
Summary
On StackBlitz (WebContainer / Node 22), the initial
vite:anonymous:authcall throws and the dev server crashes. DevTools never connects.The handler in
vite:anonymous:authis declaredjsonSerializable: true. When it throws, birpc wraps the rejection into{ id, e: <Error> }and the WS transport runsstrictJsonStringifyon the whole envelope, which then fails with DF0020 becauseeis anError. The original DTK0011 is lost and the process exits.Environment
Log
Suggested fix (by Claude Code)
jsonSerializable: trueis a contract about the result, not about thrown errors. The error slot (e) should not be passed throughstrictJsonStringify; coerce it to{ name, message, stack }or use structured-clone serialization regardless of the flag.This also makes the underlying handler failure (DTK0011) visible instead of masked by DF0020.
Reproduction
https://stackblitz.com/github/baseballyama/vite-devtools-svelte
System Info
System: OS: macOS 26.3 CPU: (12) arm64 Apple M4 Pro Memory: 111.70 MB / 48.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 24.13.0 - /Users/baseballyama/.nodenv/versions/24.13.0/bin/node npm: 11.12.1 - /Users/baseballyama/.nodenv/versions/24.13.0/bin/npm pnpm: 10.25.0 - /Users/baseballyama/.nodenv/versions/24.13.0/bin/pnpm bun: 1.3.11 - /opt/homebrew/bin/bun Deno: 2.5.6 - /opt/homebrew/bin/denoUsed Package Manager
pnpm
Validations