Thursday, March 5th, 2009

The Art of Throwing Errors in JavaScript

Category: Debugging, JavaScript

<p>Nicholas Zakas recently wrote a piece covering the basics of throwing errors in JavaScript:

You can throw an by using the throw operator and providing an object to throw. Any type of object can be thrown, however, an Error object is the most typical to use:

  1. throw new Error("Something bad happened.")

When you throw an error in this way, and the error isn’t caught via a try-catch statement, the browser will display the error text in the browser’s typical way.

He provides a few more details on how error handling works in browsers, and then goes on to assert that:

All JavaScript libraries should throw errors from their public interfaces for known error conditions. YUI/jQuery/Dojo/etc. can’t possibly anticipate when and where you’ll be calling their functions. It’s their job to tell you when you’re doing stupid things. Why? Because you shouldn’t have to debug into their code to figure out what went wrong. The call stack for an error should terminate in the library’s interface, no deeper. There’s nothing worse than seeing an error that’s 12 functions deep into a library; library developers have a responsibility to prevent this from happening.

A quick glance at, oh, pretty much any of the popular JavaScript frameworks out there shows that this advice is followed sparingly. Is he right that our libraries should be failing fast? Is that the “art of JavaScript”, as he asserts, or is it the art of Java, etc. being brought to JavaScript? Do you follow this practice in your code?

Related Content:

Posted by Ben Galbraith at 12:52 am
25 Comments

+++--
3.9 rating from 23 votes

25 Comments »

Comments feed TrackBack URI

It’s always amazing to me when I see something that I’ve always taken as basic common sense and all of a sudden people write papers on it and get rich and famous off it :) Guess I need to start writing up every stupid little thought that goes through my head! On second thought, that could only really ever lead to the inside of a jail cell, so never mind ;)
-
I for one agree with Nicholas’ basic premise and have been doing this in my own code for some time. Debugging modern JS libraries, by and large, is far more painful than it needs to be (debugging your apps using them I mean, not debugging the library itself). I personally am a HUGE fan of Ext JS for instance, but I dread ever seeing an error because I know it’s going to be a pain to track down, even with my faithful companion Firebug at my side. Ditto for Dojo, and as Ben said, most others.
-
The more we can learn from our experiences in other languages, such as Java, the better. Commenting structure, thinking in terms of objects and classes, and yes, throwing exceptions/errors from the public interface when possible are all good concepts that we’ve been doing for years, and they make sense in JavaScript too. A lot of my time at work these days is spent mentoring junior team members, in both JavaScript and Java, and I’ve been preaching this “take what works from Java and do it in JavaScript” advice for a while, and to positive effect, by and large.
-
Although, I have to say, I don’t agree with *everything* Nicholas says… for instance:
-
“Errors should only be thrown in the deepest part of the application stack which, as discussed previously, typically means JavaScript libraries. Any code that handles application-specific logic should have error handling capabilities and should therefore be catching errors thrown from the lower-level components.”
-
What’s good for the goose is good for the gander, meaning your application winds up having its own internal API, all the functions you call to do things. What’s wrong with throwing errors there as well? Simply stated, any function that knows of a given failure condition, but cannot handle those conditions itself should throw an error, whether its a JavaScript library or your own API doesn’t matter (this may well have been Nicholas’ intention with the part I quoted actually, just how you parse the words can subtly alter the meaning). Also:
-
“It’s important to mention that you should never have a try-catch statement with an empty catch clause; you should always be handling errors in some way. This may be different in development versus production, but it must be done. If an error happens, the answer should never be to simply wrap it in a try-catch and let it be – this masks an error rather than dealing with it.”
-
This is one of those too-rigid rules that people read and then bend over backwards trying to follow because on the surface it sounds like sound advice, but as you gain more experience you realize it isn’t always true. I’d agree however that an empty catch clause is something to be avoid MOST of the time. There are exceptions though. I’ve had situations where an error being thrown could occur but it didn’t represent an error per se (things like DOM nodes that in some cases might not be present). You can always argue there’s different ways to accomplish the same thing, and I wouldn’t argue that, but this is a valid way to do it none the less, so saying “never” do it I think is too rigid.
-
Overall though, it’s a good post in my view, one with advice that I think should generally be taken.

Comment by fzammetti — March 5, 2009

The call stack for an error should terminate in the library’s interface, no deeper.

The purpose of the call stack is that the library’s interface can be found inside the stack. So you are not limited to just seeing the high level but also have access to the detailed level. If the call stack terminated at the library level, then you will never know what actually caused the bug or how to work around it.

Comment by Jordan1 — March 5, 2009

@Jordan1: I doubt Nicholas were saying all “interface level” methods do try…catch to re-throw an error without stack trace. I believe he meant that if you are using the interface in the wrong way, it should be the interface that tells you (fail early) and not some internal function. If you ever see an error whose stack trace comes from the inners of the library, it would mean it’s a bug in the library, not in your code.

Comment by tbroyer — March 5, 2009

After almost two years developing using jQuery I can’t barely remember the time I had to debug the library code to solve a problem. The only case I can remember was due a .clone() function bug, which has been corrected in a recent release. In my opinion, if you need a library that “tells you when you’re doing something stupid” you should review your development concepts, because every library out there has a correct way of being implemented, if you do not understand how that way works you should just read the documentation, which in every library out there is rich and accessible.

As matter of fact, implementing errors throws would just bloat the library code and increase it’s size and that’s just too much of a cost for a problem that can be solved through research.

Comment by daitro — March 5, 2009

This is not a good idea for two very important reasons.

1. Performance

If you run Firebug profiler on MS Ajax, you’ll find that a gigantic portion of execution time is spent doing things like checking for incompatible types and invalid numbers of arguments. This is ridiculous. With a clean API and solid documentation there is no need for the library to babysit you. When the library does something unexpected, look to the docs.

2. Cruft

Again, look to MS Ajax. The size of the library could be greatly reduced by removing this inordinate amount of error checking. This is a mental tax levied on the developers every time they debug an issue.

—–

When a developer does something like $.trim(35), I don’t need to spend time telling them why its wrong. They need to check the documentation.

Comment by braddunbar — March 5, 2009

“You can throw an by using the throw operator”

syntax error

Comment by Nosredna — March 5, 2009

Until JavaScript is faster in all browsers (including IE), I don’t want the JS libraries doing any extra checking. I want them to go fast. Java’s VM is now pretty fast, so it can afford to do sanity checking in libraries.

However, I’d gladly accept two versions of the library–a debug and a release.

Comment by Nosredna — March 5, 2009

@braddunbar, daitro

What you need is to pass a param “-debug” to your build process, and flag all your debug/throw instruction.

This way you can build one clean file for maintenance, and a minified one for production.

Comment by ywg — March 5, 2009

Throwing errors would bloat libraries, and divert library developers’ time from projects that I think would be more useful. I would rather not have it.

Comment by WillPeavy — March 5, 2009

@ywg

I still hardly see how that would be any useful, with firebug and jslint you are pretty much covered. Any doubts? Check the docs. Simple as that. If you need a library that checks your stupidity you can try ajax.net

Comment by daitro — March 5, 2009

If you work alone or with a “standard” library, maybe.
But in a team project, this could make the difference between hard to exploit (or even rejected) code, and good work.
Especially with javascript which still has a bad reputation… Delivering irreproachable code and taking your co-workers by the hand is sometimes necessary.

Comment by ywg — March 5, 2009

There’s a danger in seeing the frameworks as a kind of magic box that does things for you that you don’t understand.

I’m all for not reinventing the wheel, but it’s definitely important as a programmer to have a modicum of understanding of the tools you are using – at least to your personal capacity if you are ‘not quite there yet’.

Comment by neonskimmer — March 5, 2009

>>Especially with javascript which still has a bad reputation…

It does?

Comment by Nosredna — March 5, 2009

I’ve gone back and forth on whether to do this kind of error checking in SwfHTML (http://code.google.com/p/unfocus-history-keeper/source/browse/trunk/javascript/SwfHTML.js ). I’ve become pretty comfortable in this instance. The errors have saved me a bit of work a number of times, by tracing an incorrect setting to Firebug, where if I hadn’t used error checking I would have let those settings fail silently. In this example though, there are not a lot of performance issues, since this is a pretty basic object in scope – but still, I do find throwing errors to be a tremendous time saver, especially when you have to utilize some library or bit of code that you haven’t used in a while.

Comment by CaptainN — March 5, 2009

Performance is of course a valid consideration here. But, for those of us that have been doing Java development for a long time you can recognize that we’re at a stage with JavaScript where we were with Java a few years ago: there’s some really good ideas that you shy away from on the grounds of performance. I think this is one of them.
-
For example, it used to be common knowledge that you should using StringBuffer in Java as opposed to simple string concats. With modern VMs though, this isn’t much of a consideration because they optimize that sort of thing behind the scenes anyway. In light of that, code readability becomes the bigger concern (putting aside the debate about whether string concats actually are more readable or not!)
-
Similarly, we’re starting to get super-fast JS engines and so at some point we have to start thinking more about readability and maintainability of code than performance, at least in some instances (you should *never* simply forget performance of course, just that sometimes it’s OK to put it on the back burner in favor of other considerations). It’s of course valid to debate whether this throwing errors idea is good or not in the first place, but if you think it is as I do then at some point the consideration of writing “better” code takes precedence over performance.

Comment by fzammetti — March 5, 2009

@fzammetti,

The speed improvements to JavaScript are great. It’s just that our grandmother is in the room (IE6), and she keeps interrupting the conversation by saying, “what, what, what?”

Comment by Nosredna — March 5, 2009

@Nosredna: HAHA, I like that!
-
Ironically, and I’ve said this on numerous occasions: I’ve actually seen BETTER performance in many cases with IE6 than IE7, FF3 or Opera9 (I don’t use Chrome, or Safari so can’t really compare them). Don’t get me wrong: I have *NO* trouble believing that is due to factors other than the browser itself, i.e., configuration, network, whatever, but I’ve seen it time and again in direct contradiction to what most of the “experts” always claim.
-
Still, great line :)

Comment by fzammetti — March 5, 2009

fzammetti,

Anything calculation bound, I’ve NEVER seen IE6 do well on. But I’m willing to believe that there are real world problems where it does happen. There are many potential bottlenecks in the world of browsers. Everyone seems to be doing something a bit different. Just look at the wars between benchmarks.

Comment by Nosredna — March 5, 2009

“null has no attribute named render”

Do I need to say anything more? Yes, throwing exceptions is the only way to ensure proper inputs. People shouldn’t have to always read documentation to figure out how something works. I don’t see how it introduces huge performance penalties as long as you design your functions right.

Comment by kumar303 — March 5, 2009

The main reason why I don’t use exceptions in JS is the code size. Adding thousands of throws takes lots of space. But I guess one could have two versions of their scripts one with error checking enabled that could be used while developing then another production version that doesn’t do all the error checking.

One could use a JS preprocessor to remove that error checking logic. I’ve blogged about such a thing a few days ago. http://blog.moxiecode.com/2009/03/02/javascript-build-process-using-ant/

Comment by Spocke — March 5, 2009

I agree with kumar303 here, and I’d go a step further and say a good API should intentionally minimize the number of times you need to consult documentation. With a good API, I can give you a simple list of method signatures, including exceptions that can be thrown, and that will largely be all the documentation you usually need. The method names reflect their function, the argument names reflect what they are and the exception information tells you what can typically go wrong (it’s all a little trickier in JavaScript of course, as dynamic as it is, but still).

Comment by fzammetti — March 5, 2009

I think at least some JS widgets/modules/libraries could benefit from explicit “error callback” functionalities, where the user of a library can explicity subscribe to know about certain internal (non-api-abuse related) and unforseeable events. For instance, I have an XHR clone library (called flXHR http://flxhr.flensed.com/ ) which exposes an “onerror” callback handler which will send all errors to that callback if defined. Otherwise, it throws them as javascript errors. I think this is the best of both worlds. And it’s really not that much extra code to do so.

Comment by shadedecho — March 5, 2009

@braddunbar: please check before you make such uninformed statements. Microsoft Ajax, like most JavaScript libraries, comes in two flavors: minimized/release and debug. The error checking code is very extensive but is only present in the debug version, as it should. The release/minimized version has no error checking except on errors that might make sense for the end user and that are not developer errors (network timeouts and such).
As Microsoft Ajax has shown since the first version, it is entirely possible to provide meaningful error messages and stack traces to application developers without compromising performance, by only instrumenting the debug version.

Comment by BertrandLeRoy — March 5, 2009

@BertrandLeRoy I did not know that the error checking was taken out of the production version. Thanks for pointing that out, and my apologies for any misrepresentation I gave.

Comment by braddunbar — March 5, 2009

@braddunbar: no problem. I apologize myself for being a little rude.

Comment by BertrandLeRoy — March 6, 2009

Leave a comment

You must be logged in to post a comment.