You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Calling abort() will also destroy the stream with an error.
Destroying the stream emits an 'error' event on the PassThrough stream, and because there's no error handler attached to that stream, this crashes the entire process (see stacktrace below). This stream isn't exposed (only used through the pipe(writable) wrapper function), so consumers are unable to add an error handler for this themselves.
(Error caused by a reference error inside the Preact component that's being rendered)
node:events:496
throw er; // Unhandled 'error' event
^
ReferenceError: aaaa is not defined
at Object.Component (/persist/f0x/projects/preact-streaming/lib/views/index.js:17:5)
at _renderToString (/persist/f0x/projects/preact-streaming/node_modules/preact-render-to-string/dist/stream/node/index.js:362:27)
at renderToString (/persist/f0x/projects/preact-streaming/node_modules/preact-render-to-string/dist/stream/node/index.js:159:22)
at renderToChunks (/persist/f0x/projects/preact-streaming/node_modules/preact-render-to-string/dist/stream/node/index.js:679:17)
at renderToPipeableStream (/persist/f0x/projects/preact-streaming/node_modules/preact-render-to-string/dist/stream/node/index.js:766:3)
at renderStream (/persist/f0x/projects/preact-streaming/lib/render-stream.js:35:65)
at /persist/f0x/projects/preact-streaming/lib/index.js:17:5
at Layer.handle [as handle_request] (/persist/f0x/projects/preact-streaming/node_modules/express/lib/router/layer.js:95:5)
at next (/persist/f0x/projects/preact-streaming/node_modules/express/lib/router/route.js:149:13)
at Route.dispatch (/persist/f0x/projects/preact-streaming/node_modules/express/lib/router/route.js:119:3)
Emitted 'error' event on PassThrough instance at:
at emitErrorNT (node:internal/streams/destroy:169:8)
at emitErrorCloseNT (node:internal/streams/destroy:128:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
Node.js v20.18.1
There could be an internal error handler attached to the stream which ensures the process doesn't crash, and could call the existing options.onError() hook (or a differently named error callback).
Or the raw stream could be returned from renderToPipeableStream so users can add the error handler themselves, or even use the stream with the more modern stream.pipeline method, which also makes it easier to handle errors properly.
The latter would also allow directly setting response.body = stream when used with the koa webserver.
The text was updated successfully, but these errors were encountered:
const{ h }=require("preact");const{ renderToPipeableStream }=require("preact-render-to-string/stream-node");functionMyComponent(){consta=aaa// ReferenceError}try{conststream=renderToPipeableStream(h(MyComponent),{onError(e){// doesn't catch the errorconsole.error("caught error",e);},});// can't do stream.on("error") because the actual PassThrough stream isn't exposed}catch(e){// doesn't catch the errorconsole.log("caught error",e);}
fwiw I checked this same code with React 19 and the ReferenceError is passed to the user-provided onError handler, after which the rendering stops / stream closes
f0x52
linked a pull request
Jan 4, 2025
that will
close
this issue
Inside
renderToPipeableStream
, any errors thrown inrenderToChunks
are caught, and then used to destroy the streampreact-render-to-string/src/stream-node.js
Lines 46 to 48 in 2da38a7
Calling
abort()
will also destroy the stream with an error.Destroying the stream emits an
'error'
event on the PassThrough stream, and because there's no error handler attached to that stream, this crashes the entire process (see stacktrace below). This stream isn't exposed (only used through thepipe(writable)
wrapper function), so consumers are unable to add an error handler for this themselves.(Error caused by a reference error inside the Preact component that's being rendered)
There could be an internal error handler attached to the stream which ensures the process doesn't crash, and could call the existing
options.onError()
hook (or a differently named error callback).Or the raw
stream
could be returned fromrenderToPipeableStream
so users can add the error handler themselves, or even use the stream with the more modernstream.pipeline
method, which also makes it easier to handle errors properly.The latter would also allow directly setting
response.body = stream
when used with the koa webserver.The text was updated successfully, but these errors were encountered: