I am quite unsure how I should properly handle uncaught exceptions that occurs in my node.js/express app. Right now I have an Express app that will send all caught errors to an Express error handeler using next(err):
function(err, req, res, next) {
// Do something with the error
}
This seems to work all fine and well for errors I have anticipated. For instance a database connection not working, essentially all things that will return a callback(err). Thought problem occurs when I want to preform a background task, which will finish after the response has been sent. For instance:
app.get('/url', function(req, res) {
BackgroundTask.run() // Here an uncaught exception occurs, for instance a bug
res.send('Running your background task')
}
The background modules that I want to run aren't express related (no use of req,res) and upon a caught errors they will use a custom in errorHandeler that will send the error to some error reporting service. However when an uncaught exception occurs in one of these background tasks I have no clue how to send the error to my error report service (Raygun in this case). The only thing that seems to work is to add a process.on('uncaughtException') event listener. However almost every post on the subject describes the latter a 'bad' or crude way of doing things. They seems to recommand using node domains however I don't really see how I can implement these for background tasks.
I use process.on(uncaughtException), because all you're really trying to do is catch the output from the error and shut the server down gracefully (and then restart). I don't see any reason to do anything more complicated than that, because by nature of the exception, you don't want your application doing anything else in that state other than shutting down.
Domains are an alternative way of dealing with this, but it's not necessarily better than using the process handler, because you're effectively writing custom logic to handle things that you aren't anticipating. It does give you finer granularity in terms of what your error handler does for different error types, but ultimately you're still potentially running your application in an unknown state after handling it. I'd rather have my application log the exception, shut down, and then i'll fix the error so it never happens again, rather than risking my user's data on a domain solution which may or may not have handled the error correctly, depending on the nuance of the error it encountered.
Related
I have a "ghost" express middleware, that is sometimes triggered to check stuff before a request gets answered. As it relies on some sort of reverse engineering, there's a high chance it encounters unhandled errors. I call it "ghost" precisely because it should NEVER end the request if it has an error.
Except I want these unhandled errors to be logged in Sentry, while at the same time passing the request to the next request handler. Is there any Sentry method that allows sending errors without throwing them?
For now, I simply log them with Winston at the "error" priority level, but I'm really trying to transition away from that with Sentry. Sentry contexts seem to be related with what I'm trying to do, but I didn't quite get what they are.
My bad, should have read the docs more carefully. https://docs.sentry.io/platforms/node/enriching-events/context/#passing-context-directly
So, if a new user tries to sign up with an user account that already exists, MongoDb responds with a 11000 error code
In Express, that can be handled like this:
async function signup(req, res, next){
try{
// some stuff
}catch(err){
if (err.code === 11000) {
err.message = 'Email is already taken.';
res.statusCode = 409;
}
return next(err);
}
}
For this example, I decided to respond with a 409 http status code.
However, I am not sure if it's a good approach to handle several different codes from MongoDB and assigning an http status for each of them.
What other solutions am I missing?
You can return specific responses to common errors that you might come across.
But it really comes down to how specific you want to be. You also need to consider is it really worth it to customize the response for each and every single error that can occur. Some of them might never happen depending on your configuration.
For example, ncompatibleShardingConfigVersion will never happen if you are not using a sharded cluster.
Furthermore, if the error message is supposed to be displayed at the frontend, the users don't really care about the what, why, and how of an error. What he/she knows is that it doesn't work and he/she is not happy.
You have several options:
Using conditionals like what you are doing now. Perhaps create a custom error constructor and put the conditionals in it to avoid having to repeat yourself in every single function call.
Send a generic error message to the frontend with status code 500. Log the whole error object at the backend so you can know what went wrong. You are the person who actually cares about the why, what, how, when of an error.
Personally, I will go with option 2.
I'm working with an express application. There are some express routes, as
server.get('*' , ... )
etc. which perform some common operations: authentication, validation... etc.
they also decorates the response with meaningful information: i.e. in every request to the server it gives not only the expected json/html, but also information regarding the user, some app metadata that the front-end consumes etc. etc.
Let's say all this extra metadata cames in a field called extradata in every request to the server.
Now, there is a bug that is causing a problem: instead of returning its expected response (a json with a bunch of system logs), is sending only this extradata field.
I'm pretty confident the problem is in one of the middlewares, because that code that sends the response in this case is really simple, it's just a res.send() of a json. So I believe this part of the app is requiring some module that sets a middleware which causes the error. There are a lot of global vars and implicit parameters in the app so is really difficult to debug it manualluy.
I attempted to bypass such middlewares programmatically, like:
delete server._router.stack[2];
but is causing an TypeError: Cannot read property 'route' of undefined and thus preventing my app to build: sure this is not the way to go.
so, is there a way to programmatically ignore or bypass express routes that are yet set?
Even better, is there a way to programmatically tap into express middlewares and log every request and response?
(afaik, there are libreries like morgan that logs every request, but I don't think they apply to this case since I need to discriminate between middlewares).
What I generally do is simply use the next method. You can access it by simply passing it to the callback function. Something like:
app.use(function(req, res, next) {
if(...) {
next();
} else {
...
}
}
What this is going to do is go to the next middleware.
So if I understand correctly, you can check what you exactly need in the if-statement and do things accordingly.
What I would suggest is you read the Express API documentation, especially the section about middleware, which you can find here. Moreover, try to isolate the suspects and solve the issue by removing the problem, rather than deleting handlers and trying to solve the problem the easy way.
I need catch all javascript error that happen on client browser to send to Rollbar. I tried a lot of solutions like window.addEventListener and overwrite console.error method but none of the worked for me.
Ajax errors I already get, like the jqXHR on image, but it have less information on must time.
But the message above (in red) I cannot.
How to really get all browser erros messages with React?
I don't think the error you're seeing has anything to do with React, it's thrown by your browser because your script is trying to make a cross domain request.
Have a look at this for more details:
How does Access-Control-Allow-Origin header work?
I think it's not really possible to catch all browser errors in the one place, and it is not a problem of React.
For example, if you want to catch all API errors, the basic technique is to wrap all your API calls to simple function like:
/**
* #returns Promise
*/
export default function httpRequest(type, path, params, headers) {
return someHttpLibrary.request(type, path, params, headers)
catch((error) => {
logTheStuff(error);
});
}
And you should call that function instead of directly requests. Also, the additional achieves of that technique, that you'll be able to log all requests and change library in one place if you'll need it ;D
About other errors, for example errors in Rendering or logic errors, Sentry team wrote nice article about handling errors:
https://blog.getsentry.com/2016/01/04/client-javascript-reporting-window-onerror.html
And also, Sentry is very nice tool to handle React errors: https://getsentry.com/for/react/
I'm playing around with implementing a JavaScript server ping tool based on the accepted answer given on this question: Is it possible to ping a server from Javascript?. This essentially works by assuming the pinged server is down if no response has been given after n milliseconds.
That's great, and it's a pretty cool way of doing it, however there are two rather large pitfalls:
Not all servers do respond within the allocated time.
Sometimes an ERR_CONNECTION_TIMED_OUT error is thrown before our timeout timer has finished.
Both of these things cause incorrect results. The former suggests that the server is offline when it's possibly online and responding slowly, and the latter suggests the server is online when it's (likely) offline.
In an ideal world this code would capture what type of error thrown was thrown and handle this appropriately. After all, if the error thrown is a 404 Not Found error, this counter-intuitively means the server is online and has responded.
If we log the image error event, the only thing we see surrounding the error is:
Event {
...
type: "error"
}
There's no message or anything hinting at what the error thrown was, and both the 404 and ERR_CONNECTION_TIMED_OUT errors give identical information.
What can I do to capture the ERR_CONNECTION_TIMED_OUT error I see in Chrome's JavaScript console, rather than relying on a fixed-speed timer?
Update
The best way I can replicate this issue is by altering Trante's JSFiddle demo (as linked to in the question I've linked above) to use a 30000ms timer rather than a 1500ms timer:
this.timer = setTimeout(function () {
if (_that.inUse) {
_that.inUse = false;
_that.callback('timeout');
}
}, 30000);
The 'unknown' server should obviously not respond, but instead we see this:
In Chrome's console, the following error has been thrown:
Failed to load resource: net::ERR_NAME_NOT_RESOLVED
As the Image's onerror function has been fired with the generic error as given above, the function believes this to mean that 1. 'unknown' exists, and 2. it's online. The ERR_NAME_NOT_RESOLVED error appears to be something which only Chrome is aware of, and isn't passed through to the error event at all.
Update 2
Today I tried doing this with web sockets instead of images and unfortunately these suffer from the same problem. The only data surrounding the error returned is type: "error" - no information about what the error actually was.