Summary
In @qwik.dev/router@2.0.0-beta.32, the node middleware rethrows RedirectMessage (an AbortMessage subclass) before checking headersSent. RedirectMessage has no .message/.stack, so when it propagates to Vite's viteErrorMiddleware, stripVTControlCharacters(undefined) crashes with TypeError [ERR_INVALID_ARG_TYPE].
Repro
Any throw redirect(302, '/foo') in a routeAction$ or onRequest$ during vite --mode ssr. Example: a successful POST to /auth/login/ that redirects on success.
Expected
Qwik already sent the 302 response (stream closed) — the middleware should return cleanly, not forward the RedirectMessage to next(err).
Actual
RedirectMessage {}
[vite] Internal server error: undefined
TypeError [ERR_INVALID_ARG_TYPE]: The "str" argument must be of type string. Received undefined
at stripVTControlCharacters (node:internal/util/inspect:2765:3)
at prepareError (vite/dist/node/chunks/config.js:9475:12)
at logError (vite/dist/node/chunks/config.js:9504:8)
at viteErrorMiddleware (vite/dist/node/chunks/config.js:9509:3)
...
at router (@qwik.dev/router/lib/middleware/node/index.mjs:162:7)
Root cause
@qwik.dev/router/lib/middleware/node/index.mjs around line 142:
const handled = await requestHandler(serverRequestEv, opts);
if (handled) {
const err = await handled.completion;
if (err) {
throw err; // fires for RedirectMessage
}
if (handled.requestEv.headersSent) {
return; // never reached
}
}
runOnce() (in request-handler/index.mjs around line 1554) already does await stream.close() for RedirectMessage before returning it, so the response is complete — the rethrow is spurious.
Suggested fix
Check headersSent first, or short-circuit on RedirectMessage/AbortMessage:
if (handled) {
const err = await handled.completion;
if (handled.requestEv.headersSent) return;
if (err) throw err;
}
Environment
- `@qwik.dev/router` 2.0.0-beta.32
- `@qwik.dev/core` 2.0.0-beta.32
- Vite 7.3.1
- Node 22 LTS
- Platform: macOS (darwin 25.4.0)
Summary
In
@qwik.dev/router@2.0.0-beta.32, the node middleware rethrowsRedirectMessage(anAbortMessagesubclass) before checkingheadersSent.RedirectMessagehas no.message/.stack, so when it propagates to Vite'sviteErrorMiddleware,stripVTControlCharacters(undefined)crashes withTypeError [ERR_INVALID_ARG_TYPE].Repro
Any
throw redirect(302, '/foo')in arouteAction$oronRequest$duringvite --mode ssr. Example: a successful POST to/auth/login/that redirects on success.Expected
Qwik already sent the 302 response (stream closed) — the middleware should return cleanly, not forward the
RedirectMessagetonext(err).Actual
Root cause
@qwik.dev/router/lib/middleware/node/index.mjsaround line 142:runOnce()(inrequest-handler/index.mjsaround line 1554) already doesawait stream.close()forRedirectMessagebefore returning it, so the response is complete — the rethrow is spurious.Suggested fix
Check
headersSentfirst, or short-circuit onRedirectMessage/AbortMessage:Environment