Why you really want to avoid catching and rethrowing exceptions

I like processes that simply drop-dead fail when they have an unrecoverable fault.  Trying to continue is often dangerous and unlikely to actually help anyone.  This policy is all fine and well but in all cases it is vital that the “death” stack of a process be the true problem, not a generic error handler.  Those kinds of handlers ruin the lives of developers who are trying to analyze error logs, and effectively make services like Watson useless.  I can’t stress enough how critical it is to NOT mess with the failure stack.

I’ve seen many of these in the wild, including of course Microsoft code, and it means that instead of getting a nice actionable stack in the log (which would have been a Watson report in the field) you have to go back to the code and try to repro.  In the case below I stared at the source for a while trying to figure out what was likely wrong and it turned out the true problem was quite distant from the likely candidates.

2010/04/05 11:02:14 AM  BEGIN    Peek_Range TEST
2010/04/05 11:02:14 AM  ---- Exception in [StackTest] thrown type=[TestCodeException], eip=[00000004`4716C93E], message=[Index (1) is out-of-range [0..1]!]  

That was the failure right there, and that stack was the one I needed! Nothing after that should have happened... But... execution continues until finally....

2010/04/05 11:02:15 AM  Test completed exceptionally [Peek_Range]: Index (1) is out-of-range [0..1]!

The stack reported at this point is useless… the real problem was millions of cycles ago.  I'm not even including the stack from the log because it's just stupid.

The real stack can be extracted with a repro (at great pain)

And it ends up looking something like this (cleaned up)


The actual problem is in the test code!   The only useful information from the original log was basically the test that I should run.  Thank goodness it’s a 100% repro.

Comments (9)

  1. eff Five says:


    Why do you think that following pattern is so common

    catch (Exception e)


    throw e;


  2. @eff "Why do you think the following pattern is so common"?

    I think we can "blame" Java here, as Java doesn’t have a "throw;" construct (or didn’t for the longest time, assuming it has one now).

    Alternatively, we can "blame" Anders for making C# too similar to Java, leading developers to bring along their bad habits…

  3. David Levine says:

    I both agree and disagree. The problem is in the phrase: @"when they have an unrecoverable fault." – this does not capture the complexity in apps. What determines that an error is unrecoverable? Heck, what’s the difference between an error, a fault, and an exception?

    In my opinion the goal ought not to be to make life easy for the developer, it ought to be to make life easy for the user. If each time there’s a hiccup the app immediately crashes it does make it much easier for a postmortem analysis to diagnose the problem…and it also makes it much more difficult for the user to get useful work done. At a minimum it interrupts the user’s workflow, and worst case it could ruin hours of work.

    The argument for crashing early is that continuing to run after an exception is often dangerous. I agree that could happen, but it’s also possible that immediately crashing can also result in data corruption (I’ve had that happen too – among other things, files do not get closed correctly). I think crashing early is more appropriate for unmanaged code, where a bad pointer can scribble over random memory. For pure managed code, unless the runtime itself is corrupted, the application simply cannot overwrite random memory. Objects may be in invalid states but memory itself is not overwritten.

    From the perspective of fault handling most applications are still monolithic. It’s all or nothing, either everything works or we pull the plug.

    I think the reason why this is so prevalent is that the downside risk of drop-dead fail is small compared to the risk of continue-and-pray. Most application developers have not seen enough business value in writing apps that can recover from faults to change this approach. If the downside risk of drop-dead fail was to cause injury or death I think there’d be a whole different approach to dealing with errors. Unfortunately there’s not a lot of support from the design and implementation tools to help with building fault tolerant apps.

    I would like to see this change.

    An observation….simply catch-rethrow does not change the crash-not crash decision,it simply moves it further up the call stack (where it belongs). Crashing ought to be an application policy decision, not something a low-level component should decide.

  4. .NET 4 introduces a "generic error handler" (i.e., AggregateException) for code that uses the new Task class. I posted my concern over post-mortem debugging of TPL code on the PFX forums: http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/55c17b04-ca51-4f38-b02d-4a83819c1261

    Stephen Toub posted a good workaround (on that thread), which should be read by any developer who wants to use Winqual with multi-threaded .NET 4 code.

  5. Pop Catalin says:

    I wish C# would default to re throwing exceptions when "throw ex" is used inside catch blocks.

    The problem currently is simply because the behavior is counter intuitive from a usage perspective and unintuitive from a effect perspective.

    We humans are used to combine verbs with objects (especially true in programming), so it’s more intuitive to say "throw ex" than "throw;", meanwhile the desired "re throw" operation is not syntactically visible in the code when using "throw;" from a linguistic perspective.

    Maybe some day this problem will be solved at the roots and not just through education and warning signs.

  6. zzz says:

    Pop, I think that’s a great Idea. Maybe we could go further than that. Lets make the default behaviour easier to debug, even in release builds and only by jumping through some extra hoops it will throw the debug information away:

    Suppose exception is..

    try {

    //…thrown here


    catch {}

    in a release build, and then 5 minutes later the app crashes. Now in my thoughts the default behaviour, unless explicitly disabled on try{} block basis (say for perf,security reason) should be to log the stack trace on every catched exception. Maybe there could be some kind of optimization here that if same block is throw&catching exactly same thing so much that it fills whatever buffer is logging the stack traces, it will on fly optimize this throw catch to happen quicker and take less log space.

    No idea on how complicated that would be to implement though so maybe it’s not worth it.

  7. David Levine says:


    It’s easy enough to write your own code to do what you want. That’s also pretty much the way that I do it – all exceptions get logged so that there are always breadcrumbs left behind for analysis.


    I treat the use of "throw ex;" as a bug because it throws away the original stack trace. There are a few use cases where this is the correct behavior but these are rare.

    It’s too late to change the default – too many apps would break.

  8. Miral says:

    I mostly work on industrial control software — and in that, it’s definitely the rule to catch (and log) exceptions as close to the raising point as possible and then continue execution as best it can.

    (The particular control software tends not to cause injury on catastrophic failure, but it can cause damage and lots of lost money.)

  9. David Levine says:


    I also work on industrial control software. Writing fault tolerant and reliable software is very important to us.

Skip to main content