Description
I've also opened a related issue in the nodejs/node-v0.x-archive#9279 repo about this. The
error message from iojs is slightly different, but just as unhelpful in this situation.
For the sake of convenience, the rest of this post is verbatim what the issue
under the node repo had, with the minor change in error message accounted
for.
So this issue seems to have been around for quite some time. The problem
probably affects all instances where things are piped into closed streams, but a
very common example that comes up in practice is piping the output of a node
program to something else.
Let's use this as a simple (albeit contrived) example:
$ iojs -e "console.log(1);console.log(2)" | cat
1
2
When piping to something that won't consume the entirety of the stream, the
program crashes in a very unhelpful way:
$ iojs -e "console.log(1);console.log(2);" | head -1
1
events.js:141
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at Object.exports._errnoException (util.js:734:11)
at exports._exceptionWithHostPort (util.js:757:20)
at WriteWrap.afterWrite (net.js:753:14)
Categorizing this as an error in the first place is a little strange. While I
can appreciate that trying to write to a closed stream is an error in theory,
it seems really odd to crash like this when not paging through everything on
stdout.
Treating stdout as a special case may be a bit much to ask, but at the
very least, there should be some improvements to the error messaging here. The
example I gave was just using iojs -e
, but even with a proper file, no useful
stacktrace or messaging is provided. Maybe add something like:
Warning: Attempting to pipe to a closed stream (foo.js:10:12)
?
I discovered this as I was piping the output of a CLI program I'd written to
less
. When paging all the way to the bottom, no errors would be logged, but
exiting less before paging all the way through would consistently have the EPIPE
error written to stderr.
Right now, there are a few workarounds.
Users can just redirect stderr to /dev/null
like so:
$ 2>/dev/null iojs -e 'console.log(1);console.log(2)' | head -1
1
or use the epipebomb module.
Neither approach is ideal.