Swallowing Exceptions: Don't Do It!

by Charles Miller on April 28, 2003

Rank and File (yet another Blogger Without a Name) recounts a bad experience with checked exceptions:

Moving at full speed to make insane deadlines a lot of corners where cut. Exceptions became nuances rather than boons and a lot of swallowing happened.

...

...All this swallowing has left the system on precarious gound. If an error occurs, and they always do, the state of the system becomes compromised and unknown. A swallowed IOException manifests itself as a NullPointerException in subsequent requests.

Ignoring the checked/unchecked distinction for now, there are three kinds of exceptional situation:

  • The kind you can ignore. These are very rare. The only one that springs to mind right now is InterruptedException: 99% of the time it doesn't really make any difference if your Thread.sleep() has finished naturally or been interrupted.1
  • The kind you can recover from here. Maybe you need to re-establish a connection, try a different file, or just wait another five seconds and try again.
  • The kind you can't recover from here. You are now in an error state. The application will need to compensate for this error here, but you don't know how to do that here.

The only place where it is acceptable to swallow exceptions is in the first case: if the throwing of the exception means absolutely nothing to your application, that's the only time you can ignore it. Which reminds me, I often see this:

try {
    Thread.sleep(TICK);
} catch (InterruptedException e) {
    e.printStackTrace();
}

What possible use is this stack-trace? If you're going to be swallowing an exception, have the courage to swallow it silently. Either something is a problem that needs to be dealt with, or it isn't. If you can't muster that courage, if you have one of those guilty pangs every time you see an empty catch block, it's a good sign that swallowing the exception was the wrong thing to do in the first place.

For the second case, you need to have code that comprehensively deals with the error. For the third case, you need to either throw an exception yourself, or make the error part of your method's return value.

Sometimes, when you're rushed, you might just consider swallowing the exception, printing an error message, and keeping going. Maybe you don't want to have to put together a consistent package of exceptions for your application. Maybe you know there's no error handler at all. Or maybe you just don't like checked exceptions on principle. In this case, throw an unchecked exception.

If you have an error you can't swallow, that you can't deal with on the spot, and that you can't deal with higher up in your application, then your application is broken. The correct behaviour for a broken application is to crash immediately. A broken application that tries to limp onwards in an inconsistent state is a danger to itself, its data, and ultimately its users. The best way to make sure this happens is to throw an unchecked exception. If someone knows how to deal with the error, they'll catch it eventually. Otherwise, it'll cause your application (or at least the current use-case) to die without causing any further damage or corruption.

1 So much so, that I wish they'd done away with the exception entirely, and just had Thread.wasInterrupted() instead for the rare case it was important.

Previously: Classic Testing Mistakes

Next: Mac vs PC. A parable.