Problem: Although duplexify auto-wraps readable streams that do not appear to be streams2 implementations, errors emitted by the streams2 wrap (e.g. bubbled up from the wrapped stream) are unhandled and will mostly likely crash the current process unless you're lucky enough for the current call stack to have a try/catch in it somewhere.
An example from my use case is in the Azure Storage SDK where most of its stream functions return a custom stream instance called a ChunkStream which, to duplexify, doesn't appear to be streams2.
Repro:
> process.version
'v8.11.4'
> through2=require("through2"),duplexify=require("duplexify"),ChunkStream=require("azure-storage/lib/common/common.node").ChunkStream
...snip...
// Streams2
> thru=through2(),dup=duplexify(null,thru).on("error",console.log.bind(null,"dup caught it"))
...snip...
> thru.emit("error", new Error("boo"))
// OK; the only evidence of the error is through the handler I established
dup caught it Error: boo
...snip (call stack)...
// Non-Streams2
> chunk=new ChunkStream(),dup=duplexify(null,chunk).on("error",console.log.bind(null,"dup caught it"))
...snip...
> chunk.emit("error", new Error("boo"))
Error: boo // <<< OH NO! This is an unhandled error and may crash the process
// The error handler on dup also runs because unhandled errors don't crash the REPL
dup caught it { Error: boo
...snip...
Suggested Fix: Apply equivalent "end-of-stream" behavior to this._readable2 as this._readable has.
Problem: Although
duplexifyauto-wraps readable streams that do not appear to be streams2 implementations, errors emitted by the streams2 wrap (e.g. bubbled up from the wrapped stream) are unhandled and will mostly likely crash the current process unless you're lucky enough for the current call stack to have atry/catchin it somewhere.An example from my use case is in the Azure Storage SDK where most of its stream functions return a custom stream instance called a ChunkStream which, to
duplexify, doesn't appear to be streams2.Repro:
Suggested Fix: Apply equivalent "
end-of-stream" behavior tothis._readable2asthis._readablehas.