I noticed that rollbar items are not reported for errors that occur in callback in chrome.tabs calls. For example the following error will not get reported:
chrome.tabs.getCurrent(function(currentTab) {
throw "This is critical";
});
If the throw statement is outside of the chrome.tabs callback, it gets reported to rollbar as expected.
The behavior is the same regardless if it happens in a background script, or a extension page accessed through a chrome-extension:// url.
Is there a solution that will allow rollbar to track errors in these callbacks?
Errors thrown in chrome API callbacks, do not seem to be caught by the onerror listener. Here is a related discussion from the chromium project: https://bugs.chromium.org/p/chromium/issues/detail?id=357568
Chrome itself behaves strangely in the tabs callbacks, even when not using Rollbar.
Here is the test code I used:
chrome.tabs.getSelected(null, function(tab){
console.log('tabs callback', window);
throw 'Error in tab';
});
setTimeout(function(){
console.log('timeout callback', window);
throw 'Error in timeout';
}, 100);
For the timeout callback, both the background console and the Errors view for the extension show the correct code location for the exception.
However, for the tabs callback the location is shown as _generated_background_page.html with no backtrace or line numbers, both in the console and in the Errors view. Chrome itself doesn't seem to know more about where the error came from.
The window object in both callbacks does have the onerror hook set correctly to Rollbar's handler. However in the tabs example, it never gets called. Chrome appears to be catching the error before it gets to the onerror handler, or whatever kind of thread this is doesn't even use the onerror handler.
As a workaround, I tried wrapping the code in a try/catch, and reporting to Rollbar:
chrome.tabs.getSelected(null, function(tab){
try {
console.log('tabs callback', window);
throw 'Error in tab';
}
catch (e) {
console.log('error', e);
Rollbar.log(e);
}
});
This works, but the error object still reports its location as _generated_background_page.html. At least it does have the correct error message.
Related
Is it possible to catch and ignore errors in a Mongoose post-save hook, resulting in a successful return (resp. a resolved promise) from a document save call?
Sample code:
schema.post('save', function postSave(err, doc, next) {
if (err.name === 'MongoError' && err.code === 12345) {
// this does not work the way I'd expect it to
return next();
}
return next(err);
});
The above hook still results in the save call failing with the original error (next(null) doesn't help either). I can replace the error by passing a custom one to next, which shows that the mechanism is generally working, but that doesn't really help me.
The Mongoose middleware docs contain a very similar example (see the "Error Handling Middleware" section near the bottom), but don't really explain the intended behavior of the next callback.
For context, what I'm trying to accomplish in the actual project is a post-save middleware hook that retries the save call when a duplicate key error is encountered.
However, there is a special kind of post middleware called "error handling middleware" that executes specifically when an error occurs. Error handling middleware is useful for reporting errors and making error messages more readable.
I think it is too late in the hooks chain to do this. It would seem that the pre "save" hook would be a good place to check for duplicate keys no? There you can error out and then in your code re-try as you see fit.
The error handling middleware is more of an error formatting mechanism really.
executed following code in the console
Notification.requestPermission(function(status) {
console.log('Notification permission status:', status);
});
in Chrome v 61
return
Notification permission status: "granted"
if already given otherwise pop-up appears near the left side of the address bar with Allow and Block option.
Although after several attempts then chrome also stop displaying the pop-up and gives information to the user in console.
and return
Notification permission status: "denied"
with message
Notifications permission has been blocked as the user has dismissed
the permission prompt several times. See
https://www.chromestatus.com/features/6443143280984064 for more
information.
BUT
in Firefox developer Edition v 57
return Promise object as below
Promise { <state>: "pending" }
why am I not getting the console message and neither does pop-up appears.
So my question is do I need to configure something in firefox?
or I am lacking something.
Note: I have tried both variations of requestPermission function suggested on MDN.
Promises and callbacks are executed asynchronously. What you see when you run this if Firefox is the temporary return value of the promise that the console.log will get executed in the future. The console.log is not however getting executed yet.
>> Notification.requestPermission().then(function(permission) { console.log(permission); });
← Promise { <state>: "pending" }
Basically what you see is working as intended. It's similar to doing something like this:
>> let thing = Notification.requestPermission().then(function(permission) { console.log(permission); });
console.log(thing);
Promise { <state>: "pending" }
← undefined
granted
The console.log(thing) is logging the promise that work will happen in the future but the permission grant and the console.log(permission) has not been executed yet.
Also the Notification.requestPermission(callback); format has been deprecated and should not be used.
Let's say I have this server route (using expressjs):
app.get('/cards', function(req, res) {
anUndefinedVariable // Server doesn't crash
dbClient.query('select * from cards', function(err, result) {
anUndefinedVariable // Server crashes
res.send(result.rows)
});
});
When I simply reference an undefined variable at the root of the /cards route callback, the server doesn't crash, but if I reference it in the nested callback it crashes.
Is it because Express is catching the error when it's at the root level? Why doesn't it also catch the errors in the nested functions?
I tried catching the error like this myself:
app.get('/cards', function(req, res) {
try {
dbClient.query('select * from cards', function(err, result) {
anUndefinedVariable
res.send(result.rows)
});
} catch (e) {
console.log('...')
}
});
But it never enters the catch block. Maybe this is the reason Express isn't able to catch the error. Is it because that, in order to be able to catch an error, you need to do it on the function that actually calls the callback? E.g. try {functionThatCallsTheQueryCallback() } catch(e) {...}? I don't think so, as query certainly calls the callback indirectly at a certain point.
How would I go about catching all errors so that my server never crashes?
try...catch only catches errors that occur in synchronous operations. It won't catch errors that occur in callbacks to async operations, like you have in your second example above.
As for the first example, express handles errors that are thrown synchronously and sends a 500 response to the client.
You can look into domains for handling errors across async operations. But be aware that they are pending deprecation. It's worth reading through the warnings in the docs about why they're being deprecated.
It can done in node, although generally not recommended, by letting node to handle the uncaughtException event,
https://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception
process.on('uncaughtException', (err) => {
console.log(`Caught exception: ${err}`);
});
Another more preferable approach would be just let it crush, and have it restarted automatically afterward. There are some tools available for this, such as nodemon, pm2, forever...
I'm using Nodejs in my windows machine. the question is Nodejs always terminate process on errors e.g. empty Mysql insert statement.
So in production time, and without manual error handling, how can prevent NodeJs exit?
example code:
app.post('/api/accounts',function(req,res){
pool.getConnection(function(error,connection){
connection.query('insert into accounts set ?',req.body,function(err,results){
if (err) {
throw err ;
} else {
console.log(results) ;
}
});
});
console.log('post received') ;
console.log(req.body);
});
Imagine i post an empty req.body.
nodejs will exit on error like this
\node_modules\mysql\lib\protocol\Parser.js:77
throw err; // Rethrow non-MySQL errors
^
Is it possible to configure something in node to just show errors but don't exit?
It's not really a good thing to be continuing execution after a unhandled exception has been thrown by the interpreter (as Ginden said in his answer) - anything could happen and it could prove to be a mistake later, any sort of hole could easily be opened by stopping the process from cleaning up after something went so unexpectedly wrong in your code.
You could sensibly add a event handler for unhandledException like the answer by Ginden points out, however, it seems you're using express and it would make much more sense actually handling the error with middleware when it happens, instead of using throw as per your code.
Replace throw err; with return next(err); and that should mean the request will fall through to the next set of middleware, which should then handle the error, do some logging, tell the user, whatever you want it to do.
app.use(function(err, req, res, next) {
// Maybe log the error for later reference?
// If this is development, maybe show the stack here in this response?
res.status(err.status || 500);
res.send({
'message': err.message
});
});
Don't try to prevent process shutdown. If error was thrown, anything could happen.
Warning: Using 'uncaughtException' correctly
Note that 'uncaughtException' is a crude mechanism for exception handling intended to be used only as a last resort. The event should not be used as an equivalent to On Error Resume Next. Unhandled exceptions inherently mean that an application is in an undefined state. Attempting to resume application code without properly recovering from the exception can cause additional unforeseen and unpredictable issues.
Exceptions thrown from within the event handler will not be caught. Instead the process will exit with a non zero exit code and the stack trace will be printed. This is to avoid infinite recursion.
Attempting to resume normally after an uncaught exception can be similar to pulling out of the power cord when upgrading a computer -- nine out of ten times nothing happens - but the 10th time, the system becomes corrupted.
Domain module: don't ignore errors.
By the very nature of how throw works in JavaScript, there is almost never any way to safely "pick up where you left off", without leaking references, or creating some other sort of undefined brittle state.
The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else.
The better approach is to send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker.
Via the Node.js documentation, an unhandled EventEmitter will crash a running process:
When an EventEmitter instance experiences an error, the typical action is to emit an 'error' event. Error events are treated as a special case in node. If there is no listener for it, then the default action is to print a stack trace and exit the program.
I would very much like for the process to not crash when this happens.[1] Ideally, I could catch every instance of an EventEmitter error like this:
emitter.on('error', function(err) { console.log(err); })
However our application is large, a simple search of the node_modules folder reveals that there are lots of EventEmitters, and tracking them down would be cumbersome.
Is there a global hook I can use to catch all instances of an EventEmitter failure?
I tried process.on('uncaughtException') but this doesn't catch EventEmitter errors. I also tried process.on('error') which catches errors emitted by the process, but does not catch errors emitted by other EventEmitters.
Other places say you should use domains, however, it sounds like you need to wrap specific function calls in it, at which point you might as well find and wrap every EventEmitter with .on('error'). My colleague also says domains are, if not deprecated, not going to be used going forward.
[1] I understand the logic behind the "processes should crash" argument. Partly I would like to keep processes alive because a) our server takes a long time to restart, and b) processes keep crashing with literally zero stack trace; I figure keeping the process alive will help with logging and tracking down errors.
process.on('uncaughtException', ...) does catch EventEmittor errors. Try this:
'use strict';
setInterval(function () {}, Number.MAX_VALUE); // keep process alive
var myEmitter = new (require('events').EventEmitter)();
// add this handler before emitting any events
process.on('uncaughtException', function (err) {
console.log('UNCAUGHT EXCEPTION - keeping process alive:', err); // err.message is "foobar"
});
myEmitter.emit('error', new Error('foobar'));
Note that if you add the uncaughtException listener after your error event has fired, the exception won't get caught!