How to catch an ENOENT with nodejs child_process.fork? [duplicate] - node.js

How do I catch .fork() errors that call files that don't exist?
var cp = require('child_process');
var fk = cp.fork("missing-file.js");
spews out
module.js:340
throw err;
^
Error: Cannot find module 'path-to-here/missing-file.js'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:906:3
I've tried
try {
var cp = require('child_process');
var fk = cp.fork("missing-file.js");
} catch(err) {
console.log("async error doesn't get caught here.");
}
fk.on('error', function(err) {
console.log("this never gets called");
})
process.on('uncaughtException', function(err) {
console.log("this never gets called either");
});
but none of those catch the error.
Joyent's documentation says an error event should be emitted when:
The process could not be spawned, or
The process could not be killed, or
Sending a message to the child process failed for whatever reason.
But this appears to happen prior to #1.
I looked at Handle errors thrown by require() module in node.js but the solution there doesn't work.
How do I catch this error?

There is no error here. node started just fine, failed to find the file, and then exited. None of these things will throw an error in the parent process. However, the second step ("failed to find the file") caused the child process to emit some text on its stdout, which by default was inherited from the parent process. That's the source of the text you're seeing (to suppress it, pass fork the silent: true option).
If you're trying to detect this error, you can put a handler on the close event. That handler will be called with 2 arguments, but you only care about the 1st one: the exit code. Node uses exit code 8 when it can't find the source file (although note that a script can also use exit code 8, so this isn't bullet-proof). Note that exit code 0 conventionally means the process ended successfully.
So, if you want to act on the file not being found and suppress the error message from going to stdout, you can:
var cp = require('child_process');
var fk = cp.fork("missing-file.js", {silent: true});
fk.on('close', function(code) {
if(code == 8) {
// Handle the missing file case here.
}
})

Related

Why does not a try-catch block catch a child_process spawn exception due to invalid executable path in Node.js?

const { spawn } = require("child_process")
try{
spawn("invalid/path/to/executable")
}catch(err){
console.log("exception: ",err)
}
This code raises an error and the execution of the program stops. It never prints exception: so the catch block is not executed:
events.js:183
throw er; // Unhandled 'error' event
^
Error: spawn invalid/path/to/executable ENOENT
When run with a valid path to an executable, the same code works.
What can I do to handle the case when the spawn fails due to ENOENT error?
This module fires error event and you can just add a listener for it.
You can read more about it here
So, you can transform your code to:
const {spawn} = require("child_process")
const subprocess = spawn("invalid/path/to/executable")
subprocess.on('error', function (err) {
console.log('Failed to start subprocess: ' + err);
});
Also, I suggest reading this article by Samer Buna. He covered a lot of interesting topics about this module.

Cannot find module '../dialog' (Electron fatal error)

In electron, I encounter the following error:
module.js:440
throw err;
^
Error: Cannot find module '../dialog'
at Module._resolveFilename (module.js:438:15)
at Function.Module._resolveFilename (/opt/App/resources/electron.asar/common/reset-search-paths.js:47:12)
at Function.Module._load (module.js:386:25)
at Module.require (module.js:466:17)
at require (internal/module.js:20:19)
at Object.get [as dialog] (/opt/App/resources/electron.asar/browser/api/exports/electron.js:35:14)
at process.<anonymous> (/opt/App/resources/electron.asar/browser/init.js:64:31)
at emitOne (events.js:96:13)
at process.emit (events.js:188:7)
at process._fatalException (node.js:276:26)
It happens on a child process spawn that fails in Linux. Strange because I do have a try catch block around that, yet it still results in an uncaughtexception, as seen in the code in browser/init.js from electron.asar:
// Don't quit on fatal error.
process.on('uncaughtException', function (error) {
// Do nothing if the user has a custom uncaught exception handler.
var dialog, message, ref, stack
if (process.listeners('uncaughtException').length > 1) {
return
}
// Show error in GUI.
dialog = require('electron').dialog
stack = (ref = error.stack) != null ? ref : error.name + ': ' + error.message
message = 'Uncaught Exception:\n' + stack
dialog.showErrorBox('A JavaScript error occurred in the main process', message)
}
As said, my code is in a try catch:
try {
server = childProcess.spawn(java, ["-jar", "App.jar"], {
"cwd": serverDirectory,
"detached": true
}, function(err) {
console.log("in callback");
});
} catch (err) {
console.log("here we are");
console.log(err);
}
But neither the callback nor the catch block is reached. Any ideas what is going on here and why the default dialog module cannot be found?
I found same error with electron 1.6.2
Figured it was due, when closing the application an error occur and electron want to display it in a dialog, maybe the close process has started and electron can't load this module, anyway I add:
const { dialog } = require('electron');
in main.js, no more error in console instead a dialog the error, I can fix it, After that I let the require just in case.
I hope I understand your question correctly...
If by "default dialog module", you mean the electron dialog API, then you can require that like so: const { dialog } = require('electron'). (Or in pre-1.0 versions simply require('dialog'). See https://github.com/electron/electron/blob/master/docs/api/dialog.md
Also the try/catch needs to be around the require in the child process. The try/catch you have is around the spawning of the child process in the parent. That require is failing in an entirely different node.js process, so it's not caught in the parent process that spawned it. It sounds like your child process code might work better if it looked like:
try {
const dialog = require('dialog');
} catch(e) {}
Also, if childProcess.spawn is referring to the core node module child_process, that doesn't accept a callback function. See https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
Can you share the code from your child process? That might help more.

Catching all unhandled errors in Gulp

Our Gulp build process fails for some new developers like this:
events.js:85
throw er; // Unhandled 'error' event
^
Error: EMFILE, open '[some filename]'
at Error (native)
The solution is to run:
ulimit -n 2048
So I'd like to catch the EMFILE error and replace it with a friendlier message. However, even wrapping the entire gulpfile.js in a try/catch doesn't seem to contain it.
It turns out that wrapping try/catch around everything doesn't work because the errors happen after (all) the code is executed. Injecting an error handler into every single pipe works:
function onError(e) {
if (e.code === 'EMFILE') {
console.error('Too many open files. You should run this command:\n ulimit -n 2048');
process.exit(1);
}
gutil.log(e.message);
process.exit(1);
}
...
var result = bundler.bundle();
result = result
.on('error', onError)
.pipe(source(name))
.pipe(buffer());

EPIPE write error html-pdf only on appfog server

I'm having a very weird EPIPE write error when I'm trying to generate a PDF from HTML with this module:
https://www.npmjs.com/package/html-pdf
The exact error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at errnoException (net.js:904:11)
at Object.afterWrite (net.js:720:19)
The line where I call the PDF gen:
var pdfgen = require("html-pdf");
pdfgen.create(html, options).toFile('whappbook.pdf', function(err, res) {
var errorCount = 0;
if (err) {
console.log(err);
errorCount++;
if(errorCount > 2) {
return console.log(err);
} else {
return create();
}
}
console.log(res); // { filename: '/app/businesscard.pdf' }
});
I've tried just using <h1>Testing</h1> as the HTML to see if the file was too big, but that wasn't the case.
Note: local everything works perfectly fine, but when I run this code on Appfog it doesn't work, so I suspect it has something to do with missing dependencies or file writing rights.
I'm writing directly to the home directory (in Appfog's case thats /app).
HTML-PDF is using PhantomJS and I've also directly npm'd that in my app because some people were reporting issues when it wasn't directly installed, but that didn't solve my problem either.
If there is any information that I can additionally provide please let me know!

NodeJS: throw er; //Unhandled 'error' event (events.js:72) when using child_process spawn method

I've made an node.js app to list all .txt files from a directory recursively and, for each one, do some stuff.
Here's my app.js:
var spawn = require('child_process').spawn,
dir = spawn('dir', ['*.txt', '/b']);
dir.stdout.on('data', function (data) {
//do some stuff with each stdout line...
console.log('stdout: ' + data);
});
dir.stderr.on('data', function (data) {
//throw errors
console.log('stderr: ' + data);
});
dir.on('close', function (code) {
console.log('child process exited with code ' + code);
});
When I run node app.js via console, I get the error message below:
events.js:72
throw er; // Unhandled 'error' event
^
Error: spawn ENOENT
at errnoException (child_process.js:980:11)
at Process.ChildProcess._handle.onexit (child_process.js:771:34)
I'm using node v0.10.13 at win32 environment.
I do this way (spawn) because I want to handle stdout line by line (the exec method release entire stdout as one string).
* UPDATE *
By the way, using spawn for child_process does not guarantee that the output for cmd dir will be line by line. I've created a question for that too.
That happen because dir is not a executable in Windows. It's a command from the shell.
The solution for your problem is the following:
var dir = spawn('cmd', ['/c', 'dir']);
dir.stdout.on("data", function() {
// do things
})
This exact problem was here also.
Several things:
dir is not a real executable in windows, so node.js cannot find the program you want to run.
You didn't bind an 'error' handler to your child process and the event was turned into an exception that crashed your node instance. Do this:
dir.on('error', function (err) {
console.log('dir error', err);
});
Use fs.readdir instead. It's a standard node.js API that does the same thing.

Resources