How does express.js catch ReferenceError - javascript

// Sample code
app.get("/test", (res, res) => {
return res.status(200).send(SOME_UNDEFINED_VAR);
});
In case of ReferenceError, express.js sends 500 by default.
express.js writes the ReferenceError on std out but i want to write such error on a file using my logger.
tried using
app.use((err, res, res) => {
logger.error(err) // this handler is not getting called
// this handler is only for `next(err)`
})
I know reference errors can be caught by linting tools and this case will never come but I still want to know how to catch such error.

I stumbled across the same problem.
My solution to catch references error with expressjs Error handler was to use the try and catch block inside route function and then use next(err) in the catch block. You'll have to check if the error is really a references error though.

Related

ExpressJs send response with error inside middleware

I can't understand why my ExpressJs app is crashing sending res.status(401) inside a middleware.
Let's say my start.js has:
app.use(middlewares.timestampValidator());
and the middleware is declared as follow:
timestampValidator: () => {
return (req, res, next) => {
[...]
if(error) {
res.status(401).json(new ServerResponse());
}
else {
next();
}
}
}
When the error is -successfully- sent to the client the server crashes with this error:
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async > function without a catch block, or by rejecting a promise which was not handled with > > .catch(). The promise rejected with the reason "false".] {
code: 'ERR_UNHANDLED_REJECTION'
}
But the functions is not async.
I tried calling next('error'); after sending status 401 but the app continues to routes and then the response can't be send to client because already sent.
I got the same thing in my nodejs application. My middleware was crashing in the application, and after some time of the crash, the unhandlesPromiseRejectionException was raised. The middleware is not async, but this crash is stopping the execution of the code (if try catch is not used to handle it), thereby terminating the entire process and then after a while the exception is raised.
If you notice the time of error receiving on the client, you could see that you get the error on the client sooner and the PromiseException gets raised later. I would ask you to check, if the error you get on the client, is that a timeout error, or the error code that you have thrown
I think Express just raises unhandled exception in middlewares as unhandledPromiseRejection By default as it is a break in its api hittin process which is asynchronous by default. EVen though your middleware is synchronous, but it is placed in an asynchronous process of an API route, and if anything crashes in it which is not handled, it will raise an UnhandledPromiseRejectionException as it is a crash in an asynchronous process.
Try to think of it as this : -
public async randomeFUnction()
{
syncFUnction1()
syncFUnction2()
await asyncFUnction()
}
now if syncFunction1 crashes, it will still be an unhandledPromiseException, although the main stacktrace leads to a sunchronous method, but essentially, randomeFUnction is the one which has failed, which is an async function.
I would suggest to use try catch to prevent a formal crash rather than an If condition.
Let me know if it helps.

Why can't I catch error thrown from node-postgres?

I'm having an issue catching an error thrown from the Node-Postgres NPM package.
The issue seems simple on the surface, but I've tried everything I can think of.
My code is like the following:
import { Pool } from 'pg' // Import postgres connection pool
const pgPool = new Pool()
async function queryDatabase() {
try {
// Force TypeError by passing undefined
let queryResult = await pgPool.query( undefined )
if ( queryResult.rows.length > 0 ) {
return queryResult.rows[0]
}
return false
} catch( err ) {
// Never Reached
return new Error( 'Test error' )
}
}
queryDatabase()
And the error is as follows:
TypeError: Client was passed a null or undefined query
at Client.query (~/.../node_modules/pg/lib/client.js:479:11)
The error itself is pretty self-explanatory. I'm forcing the error here, for the sake of trying to handle it in the event that undefined gets passed by mistake. I realize that I can simply perform a check to make sure the input is never null or undefined, but that's not my main concern.
My worry is if I can't catch this error thrown from this package, how many other unforeseen cases am I going to encounter where I simply can't catch and handle a thrown error.
I've tried numerous different approaches - The Async/Await Try/Catch method, shown above - I've tried pgPool.query().then().catch() - Combinations of the two. I've even tried running the catch against the Pool instance itself. No matter what I do, I can't handle the exception without using Node's process.on('unhandledRejection', ...), which is of course a bad idea.
I've been racking my brain on this for hours. Is there any way that I can catch and handle errors like this, so it's not crashing my server every time? Thanks in advance!
I was able to reproduce this and it seems to be an actual bug in the pg-library.
According to the source if you call .query on a pool instance, this instance will attempt to connect and get a client. In this connect-callback the actual query is dispatched to the client-module, which will throw the mentioned type error if the query is nil.
This error is thrown synchronously (i.e. the error is not passed to the callback argument, e.g. callback(new TypeError("...")) and since there's no try/catch around the client.query call in the pool's connect-callback, the error will not be caught by your try/catch.
A potential fix would be to wrap the client.query call in a try catch:
client.once('error', onError)
this.log('dispatching query')
try {
client.query(text, values, (err, res) => {
this.log('query dispatched')
client.removeListener('error', onError)
if (clientReleased) {
return
}
clientReleased = true
client.release(err)
if (err) {
return cb(err)
} else {
return cb(undefined, res)
}
})
}catch(err) {
return cb(err)
}
So for now, you probably should create an issue on github and wait for the bugfix or fork the repo and use above workaround, I'm afraid.

Catching exceptions when calling set in Firestore

I haven't touch JS or Firebase for a while so forgive style issues. I ran into an issue calling set on a DocumentReference. You can't have a value of undefined. That's fine, but i expected my catch block to catch the exception, but instead the whole function crashed (this is within a cloud function). I've tried to simplify the code:
app.get('/test', (req, res) => {
return db.collection('users').doc('someid').set({
first: undefined
})
.then(()=> {
res.send('it worked?');
})
.catch((error: any) => {
console.error(error);
res.status(500).send('it didn\'t work');
})
})
A couple of notes, I'm using ExpressJS and testing this in the Firebase Functions emulator, writing to the real Firestore.
So my question is why isn't the error being caught? Instead I receive a response containing the exception details. Is the solution to check values before calling set? And if so, given it isn't written in the documentation linked above, how are you meant to know that?
The issue is that the set() function is throwing the exception before returning a promise because the parameter is invalid so you should validate that your object has no undefined fields.
From experimentation I have found that it accepts nulls so here is a way to work around the issue:
let firstValue;
app.get('/test', (req, res) => {
return db.collection('users').doc('someid').set({
first: firstValue || null
})
.then(()=> {
res.send('it worked?');
})
.catch((error: any) => {
console.error(error);
res.status(500).send('it didn\'t work');
})
})
I haven't found any indication in the documentation that the set() function does not accept data with undefined fields but I don't know why you would get them there in the first place as I don't think it would be useful to store it in the database. Also it is a best practice to always initialize variables to avoid having to deal with such issues, use blank values such as "" or {} if you haven't calculated the value yet.

How Expressjs decides which error handler to call. if we have multiple error handles

I am just curious to know that how express decides which error handler to call (next(err)), when we have multiple error handlers.
If you have multiple errorhandlers, they will be called in the order you put them in your .use statements. Every errorhandler has to do next(err) though in order to pass the error on.
Taken from expressjs documentation:
app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)
As an example from the documentation:
function errorHandler (err, req, res, next) {
if (res.headersSent) {
return next(err)
}
res.status(500)
res.render('error', { error: err })
}
So an error is beeing passed from handler to handler with the next(err) statement. And within that handler you decide what to do. You could for example check for a specific error and only act on that specific error.
expressjs documentation for errorhandling

How can I convert a rejected promise to an exception and throw it from an Express route handler?

In one of my app's route handlers, I am calling a method that returns a Q promise. Rather than handling the rejection using the .catch method, I want it to be thrown and get caught by my Express app's catch-all error handler.
I tried Q's done method, but it throws the exception asynchronously, so rather than it getting handled by my catch-all error handler, it gets propagated all the way up and my app gets terminated:
// The route handler
function index(req, res) {
dao.findById(id).then(function (data) {
res.send(data);
}).done();
}
// The catch all event-handler
function catchAllErrorHandler(err, req, res, next) {
console.log(err, req, res);
}
// Registration of the catch-all event handler
app.use(catchAllErrorHandler);
The error never enters the catch all error handler. Is there a way to make the thrown errors get handled by catchAllErrorHandler?
This does not answer your question directly, but rather shows another way to achieve your goal.
Every middleware handler in express has the signature (request, response, next). Currently your index function does not have next defined.
When calling next with an argument, express considers that argument to be an error, and manages it appropriately.
So, in your case, change your index function to include the next parameter, and change .done() to .catch(next) which will call next with any error that occurs, and allow express to handle it.
dao.findById(id)
// Handle success
.then(function (data) {
res.send(data);
})
// Handle failure
.catch(next);
I tried Q's done method
That's probably the best you get to throw exceptions from promises.
but it throws the exception asynchronously
Of course it does, promises are always asynchronous. You cannot determine whether your promise will reject in the future and synchronously throw an exception…
Is there a way to make the thrown errors get handled by catchAllErrorHandler?
Pass the handler explicitly as a handler:
dao.findById(id).then(function (data) {
res.send(data);
}).catch(catchAllErrorHandler);
Alternatively, since Q v1.3 you can used the unhandled rejection tracking and put your catchAllErrorHandler there.

Categories

Resources