147

I'm trying to find or figure out a way to display in an alert box all of the unhandled javascript exceptions in an application. I'd want all of this to be done on the client side, without using any server side code. I'm using MVC3 as an environment.

I've been researching for the last few days and haven't found exactly what I'm looking for.

I found 2 ways below that seem like they're almost what I'm looking for, except these ways are set up so that you have to pass a function name into a custom method to print the stack trace of all unhandled exceptions within that one specific function. I'm looking for a way to not have to manually pass a function name to a custom method that prints the stack trace of all of the unhandled exceptions. I'd want these custom method to just 'listen' for all unhandled exceptions within the whole application.

http://eriwen.com/javascript/js-stack-trace/

Also something similar to the previous link:

https://github.com/eriwen/javascript-stacktrace

Here's the basic code from the 2nd link above that prints the stack trace of a specified javascript function:

instrumentFunction: function (context, functionName, callback) {
    context = context || window;
    var original = context[functionName];
    context[functionName] = function instrumented() {
        callback.call(this, printStackTrace().slice(4));
        return context[functionName]._instrumented.apply(this, arguments);
    };
    context[functionName]._instrumented = original;
}

function printStackTrace(options) {
    options = options || {
        guess: true
    };
    var ex = options.e || null,
        guess = !! options.guess;
    var p = new printStackTrace.implementation(),
        result = p.run(ex);
    return (guess) ? p.guessAnonymousFunctions(result) : result;
}

So, to sum this up, do you all know of any way to have some sort of 'listener' to listen for all javascript unhandled exceptions and then print them to the screen in an alert box?

Thanks! Jason

jgillich
  • 71,459
  • 6
  • 57
  • 85
jre247
  • 1,787
  • 5
  • 21
  • 28
  • one thing... wy would you use an alert box?!? you could use console.log(error_message) to.... – Mathlight Sep 24 '12 at 19:34
  • 1
    I think _this question_ **[Catch all JS errors](http://stackoverflow.com/questions/5328154/catch-all-javascript-errors-and-send-them-to-server)** will help you out – Pilgerstorfer Franz Sep 24 '12 at 19:38
  • You probably should have a look at this question: http://stackoverflow.com/questions/205688/javascript-exception-handling – Mark Sep 24 '12 at 19:38

5 Answers5

156

You can do this by using window.onerror method.

window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
    alert("Error occured: " + errorMsg);//or any message
    return false;
}
Nish
  • 2,296
  • 2
  • 14
  • 19
  • 20
    Much better than trying to wrap my entire app in a try/catch block. :) Thanks! – Anthony Jul 23 '13 at 21:21
  • 16
    Just a heads up: "Note that some/many error events do not trigger window.onerror, you have to listen for them specifically." -https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.onerror – shusson Mar 03 '14 at 00:33
  • 8
    there is no need to include the function name (myErrorHandler) in that code... can just be function (errorMsg, url, lineNumber) – JoelFan Feb 12 '16 at 19:40
  • 24
    @JoelFan it's better to have the function name, for debugging purposes. The debugger will use the function name instead of showing as an anonymous function. – Jerinaw Jan 19 '17 at 14:28
  • This is awesome and thanks! been trying to debug a complex photo-zooming script that works fine 100% of the time, except on mobile safai where it randomly fails, and where there is no "console" or "developer" window to see what happened. Sure I have my own "debug" window I can turn on with a secret button, but I had no way to globally see every error I hadn't done a 'try/catch on. This addition showed me EXACTLY where the problem was, and spared my tearing more hair out! Wish I could up-vote this twice! – Randy Mar 24 '19 at 17:05
  • @Randy have you tried the Safari inspector? It's not nearly as good as Chrome and Firefox but at least it's something. – Jespertheend Nov 14 '19 at 09:55
  • @Jespertheend - Thanks, but the window.onerror method offered has worked fine. Plus, I asked this 7 years back :-) Since then I've discovered the online javascript checking tools, which quickly revealed plenty of other coding "bombs" waiting to happen. Problem solved. – Randy Nov 15 '19 at 15:33
  • 5
    `throw new Error('tja');` isn't caught in lastest chrome with this approach... – OZZIE Feb 19 '20 at 11:19
  • This answer is outdated and seriously missing the event `unhandledrejection`. Also you better use `self.onerror` because `window.onerror` does not work on worker scopes. – Lewis May 17 '22 at 15:04
  • Through this method I was able to catch the moment of the error itself, but the "Uncaught TypeError" error message coming from 3rd party code was printed into my console afterwards anyway. – Ellrohir Sep 01 '23 at 06:51
66

In addition to

window.onerror = function (message, file, line, col, error) {
   alert("Error occurred: " + error.message);
   return false;
};
window.addEventListener("error", function (e) {
   alert("Error occurred: " + e.error.message);
   return false;
})

You can also catch all the errors fired inside a promise callback (.then()) listening for unhandledrejection event

window.addEventListener('unhandledrejection', function (e) {
  alert("Error occurred: " + e.reason.message);
})
Javier Perez
  • 675
  • 5
  • 6
  • 1
    Is it necessary to use both `window.onerror` and `window.addEventListener("error"`, or is using one of them sufficient? – Tormod Haugene Jul 15 '19 at 09:09
  • 4
    You can use one of them. If you use `window.addEventListener("error"`, send `useCapture` set to `true` in order to catch also elements errors that didn't bubble up. https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror – Javier Perez Jul 15 '19 at 15:28
  • 1
    Thank you!! The `error` event wasn't catching my particular error. `unhandledrejection` got it though. – joe Feb 15 '20 at 13:02
  • `throw new Error('tja');` isn't caught in lastest chrome with this approach... – OZZIE Feb 19 '20 at 11:19
  • @OZZIE it does work to me when testing it using chrome v79. https://codepen.io/sljavi/pen/abOmqEQ – Javier Perez Feb 20 '20 at 12:30
  • 1
    @JavierPerez I tested using v80 attatched the event and threw an error directly afterwards and it wasn't caught, didn't catch syntax errors either. – OZZIE Feb 20 '20 at 12:43
  • 1
    @OZZIE I just updated my Google Chrome to v80, when running the code in codepen, two messages are shown in the console, the first one, in red, is something shown by codepen, the second message says, in green, "Error occurred: tja". That's the message printed by the error handler defined in the script. – Javier Perez Feb 21 '20 at 13:31
  • @JavierPerez could it be due to that I added it inside a try-statement? – OZZIE Feb 24 '20 at 14:51
  • @OZZIE yes, for sure that's the case, the catch block should be handling the error. It's a good practice to only handle those errors the function can understand/resolve and re-throw the rest of the errors. If there is no upper try-catch, you would be able to listen for global errors using the posted scripts. – Javier Perez Feb 25 '20 at 00:24
63

You can either use window.onerror, or (amazingly!) bind to the 'error' event properly:

window.onerror = function (message, file, line, col, error) {
   alert("Error occurred: " + error.message);
   return false;
};
window.addEventListener("error", function (e) {
   alert("Error occurred: " + e.error.message);
   return false;
})

If you want to track JavaScript errors, you can try Atatus. I work at Atatus.

KittMedia
  • 7,368
  • 13
  • 34
  • 38
Fizer Khan
  • 88,237
  • 28
  • 143
  • 153
2

You have two event listeners that can be used for this: unhandledrejection and error.

The first one unhandledrejection:

The unhandledrejection event is sent to the global scope of a script when a JavaScript Promise that has no rejection handler is rejected; typically, this is the window, but may also be a Worker.

To have a global error handler for promises you can listen for this events:

// event is of type PromiseRejectionEvent
window.addEventListener("unhandledrejection", (event) => {
  event.preventDefault(); // This will not print the error in the console });

  console.log("Unhandled promise rejection"); 
  console.log(event.reason);
}  

In the usage notes, it mentions:

Allowing the unhandledrejection event to bubble will eventually result in an error message being output to the console. You can prevent this by calling preventDefault() on the PromiseRejectionEvent; see Preventing default handling below for an example.

Thus, if you don't want to see the message being logged by the environment, event.preventDefault() can be used.

The second one error:

The error event is fired on a Window object when a resource failed to load or couldn't be used — for example if a script has an execution error.

To have a global error handler for the other errors you can listen for this events:

window.addEventListener("error", (event) => {
  event.preventDefault(); // This will not print the error in the console

  console.log("Unhandled error");
  console.log(event.message);
});
Georgian Stan
  • 1,865
  • 3
  • 13
  • 27
  • This should be the preferred answer, as the `.preventDefault()` really surpressed the unwanted error message in console, while the `.onerror` function didn't – Ellrohir Sep 01 '23 at 06:48
-4

Check out http://log4javascript.org it is based on Log4J. If most of your code is wrapped in try/catch statements to handle exceptions you can make use of this library as a common interface for sending output to an always available "dialog box" or logging window that your end user could see. You could even have a button that performs a window.print() to print the contents of the dialog box to the printer or PDF. Good luck.

Robert Bolton
  • 667
  • 3
  • 8
  • 22