61

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.

10 Answers 10

70

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);
}
Sign up to request clarification or add additional context in comments.

2 Comments

The only browser that doesn't have e.stack is IE 9 and older - they make up less than 2% of browser market share according to Net Marketshare. I'm certainly not going to worry about supporting those browsers - Microsoft ended extended support for IE 8 many years ago, so I have no idea who is still using it.
IE9 is more than a decade old now, and Microsoft has fully stopped support on it.
31

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

  1. the exception was thrown by the browser (such as in response to a syntax error);
  2. 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);
}

1 Comment

I know I'm 3 years late to the party.... but I'm pretty sure that if you throw an actual exception (not just a string), you'll get that stack trace. Like so: throw new Exception('Exception!!');.
17

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.

1 Comment

This doesn't work serverside. Also, it's not modern UX.
4

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;
}

Comments

3

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.

Comments

0

It is almost identical, see the manual: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Exception_Handling_Statements/try...catch_Statement

1 Comment

I'm really interested in knowing how to extact useful information from the exception - I've rephrased my question.
0

You can use logging tools like Yahoo! UI Library - Logger to log the errors/informative messages.

Comments

0

I wrote a handy function for it


const logError = (e: any) => {
   if (console.error) console.error(e, e.stack);
   else console.log(e)
}

Comments

0

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.

Comments

0

When dealing with caught errors in JavaScript, it should be standard practice to use the cause property of an Error instance (JavaScript's flavour of error wrapping):

try {
  connectToDatabase();
} catch (err) {
  console.error(new Error("Connecting to database failed.", { cause: err }));
}

Most runtimes have decent logging support for wrapped errors now. Here is Edge's output as of version 126.0.2592.113:

Error: Connecting to database failed.
    at <anonymous>:4:17
Caused by: Error: bad luck
    at connectToDatabase (<anonymous>:2:11)
    at <anonymous>:2:3

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.