Why So Averse To Exceptions?

Posted on July 19, 2009

11 comments

Having done a number of code reviews with our team, I’ve noticed one common theme through all projects: developers weren’t sure what to do about unhandled exceptions.

One project in particular stood out as an example of extreme “sweeping crap under the carpet.” Below, I’m listing all the exception handling “strategies” employed there.

Exhibit A: a meaningless assignment

catch (Exception ex)
{
  string txt = ex.Message;
}

Exhibit B: an adult version of the above

catch (Exception XXX)
{
  string str = XXX.Message;
}

Exhibit C: a “magic” return value

catch (Exception ex)
{
  return false;
}

Exhibit D: C++ blues

catch (Exception ex)
{
  res = -1;
}

Exhibit E: a horrible case of exception swallowing

catch (Exception ex)
{
}

Exhibit F: same as above

catch { }

Exhibit G: spinning one’s wheels

catch (Exception Ex)
{
  int i;
  i=0;
}

Exhibit H: you gain what again?

catch (Exception ex)
{
  throw ex;
}

Post-mortem

Custom error pages

First and foremost, gotta have custom error pages! Showing a Yellow Page of Death to a user is an amateur mistake. At a minimum, create a generic page with some simple copy (aka “text”) and configure it in web.config (see MSDN), e.g.:

<customErrors 
   defaultRedirect="~/errors/GenericError.aspx" 
   mode="RemoteOnly" />

No ifs or buts, must have a custom error page to at least save face.

Decide how to deliver alerts of exceptions

We had a site which didn’t function correctly, but it also never reported errors. That’s because every exception was being swallowed (see Exhibit F)! That’s a very deceiving situation. The client expects their site to work, but it never reports errors. The developer simply didn’t know what to do about them.

There are lots of ways to handle and report unhandled exceptions in ASP.NET. See an old article of mine, ASP.NET Custom Error Pages. The approached are still valid.

However, my favorite tool is ASP.NET’s very own Health Monitoring. Please read Keeping Pulse on Your Site With ASP.NET 2.0 Health Monitoring to learn all you need to know about it to get going.

Health Monitoring configuration is the first thing I put in web.config on a new project. On older projects this feature is a life saver.

In fact, every time you see an error page—raw or custom—do this: head to the system event viewer. The exception will be logged for you in all its glory. Health Monitoring does this for you. To take it a step further, I always configure email alerts of the same, as described in my article.

What if SMTP is not configured? Yes, it may happen. If all else fails, exceptions are still logged with the system events. It’s much better than nothing.

What about storing errors in the database?

I’ve heard this one a couple of times. My follow-up question always is, “And then what?

  • You’re not going to run queries by hand because looking at an exception log in a tiny cell of the Results pane is futile.
  • If the database itself is giving you trouble (a very common occurrence!) then, obviously, it’s a Catch-22 situation—you can’t log anything. Kind of pointless.
  • Are you going to build a UI to sift through logged exceptions? This is going to quickly turn into one of those crappy internal projects, and most suck big time because nobody cares much about them.

Preemptive strike: no, I don’t like ELMAH.

Have someone actually do the monitoring

At the end of the day, regardless of whether you choose emails or database storage, someone has to monitor this stuff.

Why?

Because a report of an unhandled error with a full stack trace is a gift to you.

Here’s an edge case overlooked in development, QA, and for some time in production. It finally tripped. Now you know. Now you have a chance to fix it. Be grateful and don’t sweep it under the carpet.

11 comments

Damien McGivern
on July 20, 2009

Had a similar experience when I first moved to my current company. It was a case of not knowing what to do with exceptions so just swallow them up.


Steven
on July 20, 2009

Tell me, why don't you like ELMAH?

I must admit I usually use my own logging mechanism (http://logging.codeplex.com). It has a configurable fallback mechanism and allows the ASP.NET health monitoring system to be routed to the logger. The fallback mechanism allows logging to (for instance) the windows event log when logging to (for instance) the database fails.


Steven
on July 20, 2009

By the way, I must say I see exactly the same things happening (except Exhibit G) on projects I participate. Developers are swallowing exceptions, just to get the thing working (or at least, this is what they think they’re doing). The results are always bad. It results in a maintenance nightmare.
On all projects I work on I propose a design guideline that goes something like: “When you find a generic catch (i.e. catch {}) clause has no good explanation why all exceptions need to be caught; you may assume the statement is incorrect and you are allowed to remove that catch statement from the code”.
To me, it’s all about commenting your code. It’s possible that such a catch-all statement has a very good reason to be there (it doesn’t happen often, but it’s possible). But when it’s not commented, it’s impossible for anyone to guess this. Most of the time I remove this type of code when I encounter it. The result has always two phases: 1. users or developers start to complain because I’ve seem to have broken the application. 2. we find out that that particular functionality never has worked correctly and we find the real bug and fix it.


Milan Negovan
on July 20, 2009

Steven, love your Conditions project!


Re ELMAH: Any time I see an ugly DataGrid like this one, I get concerned. Very concerned, because I don't want to maintain a yet another external dependency with a drag-and-drop back end. As much as I am a buy-don't-build guy, I just can't get myself to do it...

A "solution" like this is only a little better than poking in tiny cells of a query result in SQL Server Enterprise Manager. They need to rethink usability of their back-end and make it useful.


Steven
on July 20, 2009

I think I get the point. I must say I know too little about ELMAH to criticize it. I created CuttingEdge.Logging because I wasn't happy with they complexity of the frameworks I knew (log4net and EntLib logging).

Thanks for the compliment on Conditions. Glad you like it!


David L. Penton
on July 20, 2009

have you seen http://exceptioneer.com ? Pretty good idea and has a pro/con list to comare it against ELMAH


Milan Negovan
on July 20, 2009

Dave, thank you for the tip! Sounds interesting. Will take a look.


Steven
on July 21, 2009

I watched the demo of Exceptioneer. Quite nice what they did, but none of my clients would be willing to send exception information of their systems to a public service. It would be nice to be able to install a version of Exceptioneer as a local service within an organization.


Scott Mitchell
on August 01, 2009

Milan, perhaps you can elucidate why you dislike ELMAH more. I'm not 100% clear on your rationale. It sounds like you think the reporting UI it provides is suboptimal? Is that your major complaint?

You can certainly turn off the elmah.axd page. You don't need to view the report through the built-in UI. ELMAH will deliver error reports to your inbox or can do so through RSS or even Twitter. There's also a very rich API that you can code against to create your own reporting screens or whatever it is you find lacking. Finally, the entire project is open source so you can take the code Atif has written and nudge and prod it into the shape you want, which would be more efficient than starting from scratch, I imagine.

I have been using ELMAH since its very early beta days and have found it to be an invaluable resource. Easy to setup; easy to explain to clients; does everything I need with little to no code on my behalf.


RichB
on August 04, 2009

> Exhibit H: you gain what again?

A new callstack. Otherwise the coder would have used throw; without specifying the exception reference.


Softcon
on November 13, 2009

The exception handling items (with the exception of swallowing) looks like a catalog of debugging statements left in the code.
If the catches had been wrapped with #IF DEBUG, etc, they would not have been so bad.