Can't catch exception from fs.createWriteStream() - javascript

In the main process of my Electron app, I'm trying to handle an exception thrown when creating a file that already exists. However, my catch clause is never entered, and the exception is spammed to the user. What am I doing wrong?
let file;
try {
// this line throws *uncaught* exception if file exists - why???
file = fs.createWriteStream('/path/to/existing/file', {flags: 'wx'});
}
catch (err) {
// never gets here - why???
}

The correct way to handle this case is by listening to the error event:
const file = fs.createWriteStream('/path/to/existing/file', {flags: 'wx'});
file.on('error', function(err) {
console.log(err);
file.end();
});

What I've found is:
https://github.com/electron/electron/issues/2479
I tried to replicate with pure Node.js, and it catches errors with process.on('uncaughtException', callback)
let desiredPath = '/mnt/c/hello.txt';
let fs = require('fs');
process.on('uncaughtException', function (error) {
console.log('hello1');
});
try {
fs.createWriteStream(desiredPath, {
flags: 'wx',
});
}
catch (err) {
console.log('hello');
}
//Output is: 'hello1'
I tried it with Ubuntu shell on Windows 10, in my case I don't have permissions to read that file and process.on('uncaughtException', callback) catches it correctly.

Related

Unable to catch error from childprocess exec callback function

Context
I want to execute a comand line call in the backend of my website. If this comandline call fails, I want to catch the error and throw a new custom Error.
I tried to throw the error as follows:
async function someFunction(): Promise<void> {
...
const result = exec(`some command`);
result.on('error', (error) => {
console.log(error.message);
throw error;
});
}
and
async function someFunction(): Promise<void> {
...
exec(`some command`, (error) => {
if (error) {
throw error;
}
});
}
and catch it like this:
try {
await someFunction();
} catch (e) {
...
throw new Error('Meaningfull error')
}
Problem
But the code never reaches the catch block, as it shuts down the second i reacht the throw error.
Error: Command failed: some Command: Kommando nicht gefunden. //(Command not found)
at ChildProcess.exithandler (node:child_process:398:12)
at ChildProcess.emit (node:events:527:28)
at ChildProcess.emit (node:domain:475:12)
at maybeClose (node:internal/child_process:1092:16)
at Socket.<anonymous> (node:internal/child_process:451:11)
at Socket.emit (node:events:527:28)
at Socket.emit (node:domain:475:12)
at Pipe.<anonymous> (node:net:709:12) {
code: 127,
killed: false,
signal: null,
cmd: 'some Command'
}
Waiting for the debugger to disconnect...
[nodemon] app crashed - waiting for file changes before starting...
I tried removing the error handeling attempt and the app keeps on minding its own business. I don't understand why it keeps crashing when I trie to handle an error...
I am aware, that the command fails, and I don't care. I just want to be able to handle the error.
Edit 1
I also tried a try catch arround the exec call.
try {
exec(`some Command`, (error) => {
if (error) {
throw error;
}
});
} catch (e) {
throw e;
}
But sadly the app crashes right at the throw error line.
Edit 2
I use an restify middleware based error handler
this.restify.on('uncaughtException', function(req, res, route, err) {
res.send(500, err.message);
});
As an example. The Following code is beeing handled as expected:
if (!newUser.course) {
console.log('no course selected');
throw new Error('signal/no-course'); // error is thrown and handled accordingly
}
try {
await someFunction(newUser); // error in someFunction is thrown and crashes the app...
} catch (e) {
console.log(e);
throw new Error('signal/add-user');
}
I also tried adding console.log(error) in every catch. Didn't help.
Hello I think the correct way to approach this would be to wrap it into a Promise since it is an error within a callback, if you actually want to try and catch the error where it happens, it has to be done inside the callback as far as I am aware.
Possible solution:
function someFunction() {
return new Promise((resolve, reject) => {
exec(`some command`, (error) => {
if (error) {
reject(error);
}
resolve("coding is fun 😀");
});
})
}
async function main() {
try {
await someFunction();
} catch (e) {
console.error(e)
throw e;
}
}

Mongoose and multiple save error handling

I'm using mongoose + express to build a simple MERN app.
I need to create multiple documents and save them, but I need to catch all errors.
I'm using this code and it works, but I'd like to handle all errors at once, not repeat the same code multiple times.
If I use try...catch block and remove the callback error handler, I obtain UnhandledPromiseRejectionWarning.
model.save((err, doc) => {
if (err) return console.error(`ERR ${err.message}`);
});
I've tried this:
export const init = async () => {
try {
const newDoc = new MyModel({ test: 'test'});
const savedDoc = await newDoc.save();
console.log('All done :)');
} catch (err) {
console.log('Error');
res.status(400).send(err);
}
}
But I can't catch the error: in debug mode, the program never enter the catch block and I obtain, in case of error for example:
UnhandledPromiseRejectionWarning: MongoError: E11000 duplicate key error collection
Any suggestion?
model.save()
.then(success => {
if(!success) {
// Handle your error
}
// Success
return model2.save();
})
.then(success2 => {
})
// etc..
.catch(err => {
// Handle your error
});
try{
const savedModel = await model.save();
console.log("Model created successfully");
res.status(200).send("Model created successfully");
}catch (err){
console.log(err);
res.status(400).send(err);
}

Firestore realtime listener error unhandled in node.js

I have made a function that I am exporting using node.js called return_match_uid. I am importing the function in another express routing file and am using async await, with try and catch to handle the error. But somehow, the errors produced by return_match_uid always slip and are unhandled, even though I am using the error handling for the realtime listener recommended by Firestore doc
Here is the function:
exports.return_match_uid = function return_match_uid() {
return new Promise((resolve, reject) => {
const unsub = db.collection('cities').onSnapshot(() => {
throw ("matching algo error");
resolve();
unsub();
}, err => {
console.log(err);
})
})
})
In another express router file, I am calling the function:
const Router = require('express').Router;
const router = new Router();
const {return_match_uid} = require("./match_algo");
router.get('/match', async (req, res) => {
try {
var match_user = await return_match_uid(req.query.data, req.query.rejected);
res.send(match_user);
}
catch (error) {
console.log("Matching algorithm return error: " + error);
}
})
The error I am throwing inside the function: matching algo error do not get caught by either the err => {console.log(err);}) in the function nor the try catch block in the router. It slips and causes my app to crash. It shows the following error:
throw "matching algo error!";
^
matching algo error!
(Use `node --trace-uncaught ...` to show where the exception was thrown)
[nodemon] app crashed - waiting for file changes before starting...
I am throwing an error inside matching algo error because I have some other codes in there, and there is a possibility that it produces an error. If it does, I would like to make sure that it gets handled properly.

process.on() is not a function

I'm quite new to Node.js and I'm not sure to completely understand what this error actually means:
process.on('uncaughtException', err => {
^
TypeError: process.on is not a function
I read that one should not import process because it's automatically injected. My code is like this:
var settings;
var jsonfile = require("jsonfile");
var file = "server/settings.json";
try {
var obj = jsonfile.readFileSync(file);
settings = obj;
} catch (err) {
var msg = err + ". Exiting";
console.error(msg);
throw new Error("Fatal");
}
// some other functions
process.on('uncaughtException', function (err) {
console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
console.error(err.stack)
process.exit(1)
})
module.exports.login = login;
module.exports.logout = logout;
My intentions are to exit if I cannot read the settings file. This is by design.
I'm aware other approaches might be better, but my question is why I get the error above?
I'm running Node.js 8.12.0 on Windows 7 64-bit.
if you want to add that, what you can do is use that right at the end of your app.js or server.js( whatever your file may be).
that will globally catch any uncaught errors and log them
app.listen(port, () => console.log(`app listening on port ${port}!`));
process.on('uncaughtException', function (error) {
console.log(error);
});
so exporting is not necessary...
You should move the process.on() function before the try catch, otherwise your uncaughtException event won't take effect.
var settings;
var jsonfile = require("jsonfile");
var file = "server/settings.json";
process.on('uncaughtException', function (err) {
console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
console.error(err.stack)
process.exit(1)
})
try {
var obj = jsonfile.readFileSync(file);
settings = obj;
} catch (err) {
var msg = err + ". Exiting";
console.error(msg);
throw new Error("Fatal");
}

Catching execSync errors

I'm using execSync to run a soffice command. The issue I'm having is when an error is thrown execSync just logs the error to the console there is no way of catching it. I've tried using a try catch statement but it still just logs the error to the console.
function convertToPdf(filepath, destpath) {
var cmd = 'sofice command';
try {
var res = execSync(cmd, { encoding: 'utf8' });
} catch (e) {
console.log("Errors:", e);
}
console.log("res:", res);
}
convertToPdf("test.docx");
I run this and get this back:
Error: source file could not be loaded
res:
Notice how my catch statement is never logged even though an error was clearly thrown but another Error: message is logged automatically because I'm not logging that.
try this:
function myExecSync(command, trim = true, cwd = pwd, opts = {}) {
const ret = execSync(command, { cwd, ...opts }).toString('utf-8');
return trim ? ret.trim() : ret;
}
And write stdio: 'pipe' manually to prevent childprocess.stderr output to the console. like
myExecSync(command, true, cwd, { stdio: 'pipe' })

Categories