So as the title states I would like to be able to intercept all errors that occur on the page. So starting off with the simplest way:
Add an error event listener to window and store the errors as they occur
The problem with this approach is that if the code that is causing the error is wrapped in a try catch block, the error listener never gets triggered.
A partial solution to this issue is to override the Error constructor so that any time code such as throw new Error() is called we can intercept it using our override. This approach works very nicely for user generated errors, this doesn't work for errors that originate in the browser. For example:
const a = ()=> {
const b = {};
console.log(b.c.d) // Uncaught TypeError: Cannot read property 'c' of undefined
}
try {
a()
} catch(err) {
console.log(err)
}
I would like to be able to detect that a TypeError has been thrown. Overriding the TypeError constructor does not work in this case.
Any ideas?
EDIT: The point is to be able to intercept errors that 3rd party scripts wrap with a try catch
When a Uncaught Exception is thrown in some website or web application, an error appears in the Develper tools in each browser
In Electron for instance, if an uncaught exception, the developer can set a listener and do whatever I want with the error message:
process.on('uncaughtException', function (error) {
// Handle the error
}
So, I wonder if there is an easy way to do the same in JavaScript. This could be useful in order to record and store common errors when the users are working, or in order to show what's happening to the user, who can send feedback to the developers.
Something like this could be shown instead
Sometimes, if an error occurs the app become in a unstable state where everything is frozen, and the user do not know why. I think informing about the error is important.
I found this Error JavaScript object. It can be manually thrown, but that can be used only when try and catch are used, and not for the uncaught exceptions, where the developer made some mistakes.
You can handle it as an event listener on window object.
window.onunhandledrejection = event => {
console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}`);
};
window.onerror = function(message, source, lineNumber, colno, error) {
console.warn(`UNHANDLED ERROR: ${error.stack}`);
};
Or also like this:
window.addEventListener('error', function(event) { ... })
You can read more about the unhandledrejection event on the MDN web docs here and the onerror event on the docs here
try {
// YOUR CODE GOES HERE
} catch (e) {
if ( e instanceof CustomExceptionError ) {
// ...
} else if ( e instanceof OtherExceptionError ) {
// ...
} else {
// ...
}
//OR CALL THE ALERT BOX OR ANY OTHER UI CHANGE
}
Exceptions can be suppressed in Chrome and Firefox but none of the approaches work in IE
window.addEventListener("error", function errorHandler(event) {
console.log("exception should be suppressed and not shown in the console");
event.preventDefault();
});
throw "suppress me";
and
window.onerror = function errorHandler() {
console.log("exception should be suppressed and not shown in the console");
return true;
};
throw "suppress me";
You can play with them
https://jsfiddle.net/9uj4xm3g/4/
https://jsfiddle.net/gv0pvy3b/3/
Any ideas?
UPD:
I forgot to clarify what I mean by suppressing. I would like to be able to hide SCRIPT5022 message completely by marking an error as handled.
According to https://msdn.microsoft.com/en-us/library/cc197053.aspx
To suppress the default Windows Internet Explorer error message for
the window event, set the returnValue property of the event object to
true or simply return true in Microsoft JScript.
But as you see this doesn't help with errors logged to the console
The problem here is how you're throwing the exception.
You should be doing the following:
throw new Error("my error");
Here's a reference: https://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
Is there a way in Javascript to listen to on throw events?
I want to be able to have an event handler be called even when code like this is executed:
var hi = "hi";
try {
throw hi;
}
catch (e) {
}
In chrome (and maybe firebug too) you can run this code and hit "break on all errors" and it will break on that throw line. How exactly are they doing that? Is that outside of Javascript?
How they are doing that is the JavaScript engine doesn't continue over errors, it crashes on all error, like if you compiling c++, it is not a language feature, its the browser
That's not event that's exception, the handler goes in the catch-block:
try {
//....
}
catch (e) {
// exception handling here
// or may be fire/trigger some event here
}
The answer you accepted is not correct.
If you have an error that happens not within try {} catch() {} block, then the JavaScript execution will really break at that point.
However, if you wrap your possibly breaking code in try {} catch() {}, you can use re-throw the error to be handled by one global event handler:
window.onerror = function (error) {
// access `error` object
};
try {
// for example try to assign property to non-existing object
undefinedObj[property] = 1;
}
catch (error) {
// `error` object will be available in `onerror` handler above
throw new Error(error);
}
As a C# developer I'm used to the following style of exception handling:
try
{
throw SomeException("hahahaha!");
}
catch (Exception ex)
{
Log(ex.ToString());
}
Output
------
SomeNamespace.SomeException: hahahaha!
at ConsoleApplication1.Main() in ConsoleApplication1\Program.cs:line 27
Its really simple, and yet tells me everything I need to know about what the exception was and where it was.
How do I achieve the equivalent thing in JavaScript where the exception object itself might just be a string. I really want to be able to know the exact line of code where the exception happened, however the following code doesn't log anything useful at all:
try
{
var WshShell = new ActiveXObject("WScript.Shell");
return WshShell.RegRead("HKEY_LOCAL_MACHINE\\Some\\Invalid\\Location");
}
catch (ex)
{
Log("Caught exception: " + ex);
}
Output
------
Caught exception: [object Error]
EDIT (again): Just to clarify, this is for internal application that makes heavy use of JavaScript. I'm after a way of extracting useful information from JavaScript errors that may be caught in the production system - I already have a logging mechanism, just want a way of getting a sensible string to log.
You don't specify if you are working in the browser or the server. If it's the former, there is a new console.error method and e.stack property:
try {
// do some crazy stuff
} catch (e) {
console.error(e, e.stack);
}
Please keep in mind that error will work on Firefox and Chrome, but it's not standard. A quick example that will downgrade to console.log and log e if there is no e.stack:
try {
// do some crazy stuff
} catch (e) {
(console.error || console.log).call(console, e.stack || e);
}
As Eldar points out, you can use e.message to get the message of the exception. However, in Chrome, Firefox and IE10+, you can also get the stack trace using e.stack. The stack trace will include the file and line number of the exception.
So to assemble a string with exception info, you would write something like this:
var exmsg = "";
if (e.message) {
exmsg += e.message;
}
if (e.stack) {
exmsg += ' | stack: ' + e.stack;
}
Note that you will only get a stack trace if
the exception was thrown by the browser (such as in response to a
syntax error);
the exception object is an Error object or has the Error object as its prototype.
So just throwing a string (throw 'Exception!!') won't give you a stack trace.
To take this a bit further, to catch all uncaught exceptions, you would use a window.onerror handler (similar to .Net Application_Error handler in global.asax). The drawback of this used to be (and mostly still is) that this wouldn't give you access to the actual exception object, so you couldn't get the stack trace. You'd only get the message, url and line number.
Recently, the standard has been extended to give you the column (great for minified files) and the exception object as well:
http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#errorevent
Right now (April 2014), only Chrome 32 implements all this. IE10+ gives you the column but not the exception object. Firefox 28 still only gives you message, url and line number. Hopefully, this will improve soon. I've written about this for the JSNLog project, at:
http://jsnlog.com/Documentation/GetStartedLogging/ExceptionLogging
(disclaimer: I am the author of JSNLog and jsnlog.com)
Secondly, the .Net Exception object supports inner exceptions. It also has a Data property so you can attach key value pairs with for example variable values. I sort of missed that in JavaScript Error object, so I created my own Exception object, also as part of the JSNLog project. It is in the jsnlog.js file in the jsnlog.js Github project (https://github.com/mperdeck/jsnlog.js).
Description is at:
http://jsnlog.com/Documentation/JSNLogJs/Exception
Finally a shameless plug - the JSNLog project I'm working on lets you insert loggers in your JavaScript, and automatically inserts the log messages in your existing server side log. So to log JavaScript exceptions with their stack traces to your server side log, you only need to write:
try {
...
} catch (e) {
JL().fatalException("something went wrong!", e);
}
You can use almost in the same manner ie.
try
{
throw new Error("hahahaha!");
}
catch (e)
{
alert(e.message)
}
But if you want to get line number and filename where error is thrown i suppose there is no crossbrowser solution. Message and name are the only standart properties of Error object. In mozilla you have also lineNumber and fileName properties.
I'm not sure whether or not it is cross browser or if it's what you are looking for, but I suggest you try:
window.onerror = function (err, file, line) {
logError('The following error occurred: ' +
err + '\nIn file: ' + file + '\nOn line: ' + line);
return true;
}
I had a similar problem.
Using console.table(error); worked well for me.
It displays information in a table, and also lets me expand/collapse to see more details.
It is almost identical, see the manual: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Exception_Handling_Statements/try...catch_Statement
You can use logging tools like Yahoo! UI Library - Logger to log the errors/informative messages.
I wrote a handy function for it
const logError = (e: any) => {
if (console.error) console.error(e, e.stack);
else console.log(e)
}
The modern best practice (as I understand it) is to log the error as a separate argument to console.error (or console.log, console.warn, etc...)
try {
maybeThrows()
} catch (e) {
console.error('it threw', e);
}
Trying out this approach in practice:
try {
throw Error('err') // Error object
} catch (e) {
console.error('it threw', e); // it threw Error: err
}
try {
throw 'up' // not an error object
} catch (e) {
console.error('it threw', e); // it threw up
}
I ran the above in Chrome, and Node v16. Note that node did not include a stack trace for throw 'up', but did for the proper error. Chrome included the stack for both.