How to catch an ENOENT with nodejs child_process.spawn?
Asked Answered
B

3

35

I am using spawn to spawn a long running process that sends output over time to stdio, and is read and processed by my nodejs script. The tricky part is that I cannot guarantee that the command sent will always be valid. How can I catch an error in spawning? Preferably this will not involve installing a global exception handler, since I don't want to handle any other exceptions. (If that's the only way, I would need to figure out when the spawned process has started up correctly and then uninstall the handler, which is a mess I'd rather not get into.)

The code I want to run would be something like this:

var spawn = require('child_process').spawn;

try {
    spawn("zargle");
} catch (e) {
    console.error("I'm handling the error!");
}

But this just raises an uncaughtException somewhere in the node event loop, presumably because the call is async and didn't even try to start the child process on my script's time slice.

The only exceptions that need to be caught are when spawn fails to start the process at all (for example, the name is incorrect and ENOENT is thrown). I am not (at this time) concerned with any problems the spawned process might generate on its own.


Similar but different: How do I debug "Error: spawn ENOENT" on node.js?

I know exactly why I am getting ENOENT, and I know what to change to have the error not happen. My question is how to gracefully respond to this situation if the error is unavoidable.

Becalmed answered 10/12, 2015 at 17:54 Comment(0)
O
61

As with many things in node, child processes can emit an error event. Add a listener for that and you will be able to catch it (no try-catch needed):

var spawn = require('child_process').spawn;
var child = spawn('foo');
child.on('error', function(err) {
  console.log('Oh noez, teh errurz: ' + err);
});
Order answered 10/12, 2015 at 18:2 Comment(8)
So you're totally right. I never even tried this because it didn't occur to me that spawn would selectively throw an exception or not depending on whether an error handler had been attached. (It would be nice if the docs would mention things like this to help out us node newbies.)Becalmed
FWIW error events have always been a special event in that if there are no error event listeners (and no uncaughtException event handler on process) when it is emitted, the error will be thrown. There is a dedicated section on errors here in the node docs.Order
I just tried this but it didn't work. Does this work if spawn tries to run a file that doesn't exist?Summon
You should post a new question if adding the event handler does not work for you.Order
I just copied your console message. My code is now ready to ship ;)Configurationism
child.on('error'...) - doesn't work. This event listener together with try/catch still don't catch an error.Funambulist
The official documentation reads the use of child.stderr.on('data', (data) => {}) but that wasn't working for me. child.on('error', () => {}) does work. I wonder why though.Halfon
I'm just here for the "Oh noez, teh errurz"Pedestrian
O
9

Like mscdex said, you have to attach the 'error' event, however, you should add try catch because some errors, like EPERM doesn't fire the error event and throw Error exception.

var spawn = require('child_process').spawn;
try{
    var child = spawn('foo');
    child.on('error', function(err) {
      console.log('Oh noez, teh errurz: ' + err);
    });
}catch(err){
    console.log("exception: "+err)
}
Oviform answered 16/2, 2017 at 0:39 Comment(2)
Can you provide an example of what do you mean? Your answer seems ambiguous and I do not know if I shluld investigate this further or not.Louella
I agree, it was not clear, I updated my answer, hoping it's more clear.Oviform
C
1

You can try to catch it with process uncaughtException event. But i believe rest of the task won't be easy though.

process.on('uncaughtException', function (err) {
  console.log(err);
});
Consuelaconsuelo answered 10/12, 2015 at 18:5 Comment(1)
Available events are: close, disconnect, error, exit, message, spawn nodejs.org/api/child_process.html#event-closeProcopius

© 2022 - 2024 — McMap. All rights reserved.