Don’t Use Try/Catch

Exception handling has been talked about a lot over the last decade and a half. However, despite a general consensus on how to properly handle exceptions, a divide on usage continues to exist. Improper exception handling is easy to spot, easy to avoid, and is a simple code (and developer) quality metric. I know absolute rules come off as close minded or exaggerated, but as a general rule you shouldn’t be using try/catch.

If an exception happens, you need to know about it. If a truly unexpected exception happens, you’re better off (most of the time) crashing than letting the application continue. This is particularly true in a web application where you’ll only crash 1 thread for 1 user while your site remains accessible. The best way to achieve both is let the exception go unhandled and log the exception in a global exception handler. Too often I see developer writing code which masks errors and make it impossible to build a quality system. Users complain about system instability, and developers are left scratching their heads with no leads on what the problems are.

What’s even more frustrating is when framework code swallows exceptions. Take a look at this example, written by Microsoft:

private void LoadImage()
{
    if (this.image != null)
    {
        this.image.Dispose();              
    }
    

    if (source != null)
    {                
        try
        {                  
            source = Path.Combine(Canvas.ApplicationPath, source);                    
            image = new Bitmap(source);                  

           IImagingFactory factory = ImagingFactory.GetImaging();
           factory.CreateImageFromFile(source, out imagingImage);
        }
        catch{}                                                      
    }
}

This is a fundamental piece of code which is part of Microsoft’s UI Framework for .NET Compact Framework. The above code is buried within their framework, but through various key APIs is exposed and used extensively. This is simply horrible code. Why would they swallow any exceptions that come out of this code? The above code means that if you try to load an image "images/critical_warning.png" which doesn’t exist, the application will continue to work normally. There may be cases where this is the behavior that you want, but those would be edge cases, and they should be decided at the application level, not within the framework.

The only time you should swallow exceptions (catch{..} or catch(Exception){...}) is in your global exception handler to avoid truly fundamental issues (and recursive global exception handling). You should catch specific exception (catch(XmlException){...}) when an exception isn’t unexpected and you know that you can safely proceed.

A system that swallows and masks exceptions isn’t a healthy system.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

42 Responses to Don’t Use Try/Catch

  1. mypakfa@yahoo.com says:

    I agree,
    I told to my programmers not use try/catch unless it must be use with proper exceptions handling to pass on higher level tier.

    But those programmer doing silly thing use try catch everywhere or on older vb uses “on error resume next”. As project manager who doing audit the code, I just simply say ugly program.

  2. Avatar says:

    Excellent article. Go see done a tremendous job. Good for you!

  3. Greg says:

    ” This is particularly true in a web application where you’ll only crash 1 thread for 1 user while your site remains accessible.”

    This isn’t really true Carl. If you have any shared state etc you’re application is now in an unknown state as a whole.

  4. imak says:

    Although not directly related to this blog but I am a beginner to unit testing/TDD. Do you have any recommended readings/books in terms of where to start?

    Keep up your good work.

  5. John Piloskee says:

    Thanks Karl
    BTW I read your free ebook. Man that’s just too good. I liked your approach. Are you considering writing another one. I would like to see write about threading. No pressure :) Its just a wish list :)

  6. karl says:

    It isn’t part of the CF, its a library released for the CF:
    http://code.msdn.microsoft.com/uiframework

  7. John Piloskee says:

    Which assembly has this code in compact framework?

  8. Bruce says:

    Try
    Me.ReadArticleAboutNotUsingTryCatch()
    Catch titleFailureEx as ArticleIsMisnamedException
    Me.SetState( MYSTATES.Unhappy )
    Throw
    End Try

  9. @Karl,
    It looks like Microsoft employees should be required to use ReSharper :) It would help them to eliminate catch {}…

    I would say: Generally, allow exceptions to occur. Use try … catch with specific exceptions only, when it is necessary to free some resources or do other specific work, then re-raise exceptions.

  10. Sally Westberg says:

    Change the title of your post you moron asshole!

  11. Nick says:

    The only time you should swallow exceptions (catch{..} or catch(Exception){…}) is in your global exception handler to avoid truly fundamental issues (and recursive global exception handling).

    I would add two exceptions to this.

    I’ll assume you understand comand query separation. A lot of exception handling could be better written as a query with a command.

    ie. if is_float_format (str) then x= float_convert (str) else print “invalid float string” + str

    naive but shows the point.

    It means that the precondition for float_covert is is_float_format.

    However, what about the case for something like inverting a matrix. The predcondition involves calculating the determiner. For a large matrix both take a lot of computation. Far better to have the invert throw an exception if you can’t invert the matrix.

    The second is some deeply recursive algorithms, as as an ATN (augmented transition network) for parsing language. Here you may be very deep in the recursion when you find the answer and want to return. It’s quicker and neater to return via an exception. Your code is smaller and cleaner, and as a result more likely to be correct. The alternative is return codes and lots of testing of return codes, or implementing your own stack separate from the program stack

  12. Elena says:

    Thank you for interesting information. I was searching this information for a long time.

  13. Hi cool article, but really the title is misleading to it’s content! I was like 0.o first time I read the title on DZone and decided to see what it says! Maybe you successfully attracted readers by the title, but still it is misleading and doesn’t reflect your point of view.

    Good article anyway

  14. Karl, I have a whole gallery of weird exception handling techniques:

    http://www.aspnetresources.com/articles/why_so_averse_to_exceptions.aspx

  15. Eric Smith says:

    Agreed – a bit of an echo of an article that I wrote a while ago:

    http://thelimberlambda.com/2009/07/15/on-exceptions/

  16. Karl, I agree with you: For me the base principle is that an application which functions in a normal way should not throw exceptions. I always try to prevent environment issue (readonly files about to be written, mal-formed XML that is about to be read…) to treat the cause before facing the symptom. There are still a few cases that cannot be anticipated upfront (especially when using VS addin API!!!) but globally but they are pretty rare. As a result, when an exception pops, I know that there is certainly a bug in the code.

    I wrote about this here:

    http://www.codeproject.com/KB/books/guidelines_exception_cs.aspx

  17. Aaron says:

    Exceptions are for exceptional conditions. Exception handling is for exceptional conditions you can do something about.

  18. Colin Jack says:

    Agree, does anyone know of a tool that you can point at a member and which will tell you any exception you might get from that member (and obviously anything it calls).

  19. Gareth Rowlands says:

    I strongly agree with Karl’s sentiment: avoid try/catch as much as possible, since when you need try/catch, you’ll know. (In contrast, you should use using whenever you can – it’s common to see try/catch when there should be a using block instead.)

    I also think they commenters talking about unit-of-work have the right idea. Serving a typical web page should normally be considered a single unit-of-work and it’s appropriate to use the web framework’s built-in mechanisms for handling failures. But if the unit-of-work is, say, placing an order (ie the Place Order button), then you’ll want special processing for that.

    But it’s not normally appropriate for individual functions to catch exceptions. From a design-by-contract point of view, a function must always either return successfully having satisfied its postcondition or terminate with an exception.

  20. Donald says:

    Dont try this at work!

  21. Remi BOURGAREL says:

    The problems with this approach are these :
    1/ If I want my app to be able to catch more than one exception : I have a web form with two mandatory field (let say latitude and longitude) , how can I do if I there is an error with the data entered in both field ?

    2/ In my app in the saving process, I write an xml file, i insert in a DB,and i call a webservice. If the remote server is down (webexception thrown), How can i delete my line in DB or delete my file ?

  22. Steve Py says:

    Not to beat a dead horse, but yeah, that title stinks. :)

    My train of thought around the handling of exceptions typically follows this:
    1) Something happens in general, a truly exceptional situation, let it bubble, inform the user, shut it down. (I.e. configuration settings invalid, DB not reachable, etc.)
    2) Something happens in a distinct unit of work, nothing is compromised but normal operation has been affected: Log the original exception, raise a unit-of-work specific exception that is displayed to the user as an alert etc. and continue. (I.e. record could not be saved.)
    3) Something happens in a distinct unit of work, normal operation hasn’t been affected, but something “extra” can’t occur, log it, eat it. (I.e. selected item could not be set.)

    Eating exceptions isn’t bad as long as someone is informed that the system is doing it and why.

  23. Daniel says:

    I agree in general, but one place I make er- exceptions – is if I want to implement a TryParse type pattern on a custom type or .NET type that doesn’t have one. (Then, it’s still a narrow catch(FormatException){return false;}

  24. I would add to that that try-finally block is a nice replacement to what developers originally planned to do with try-catch.

  25. Michael says:

    [I wrote this at work this morning and was unable to post it... Didn't want to let it go to waste so here it is.]

    Karl,

    I think that you got a bit of a beating over this post today. Like the others say this is most likely due to the title of the post.

    You are obviously ranting about the code you have found in the compact framework. Code which is obviously using global or class level variables so I have no idea how it is actually supposed to work. A LoadImage method that doesn’t return a method just seems odd. We’ll let that go for now but can easily see how this frustrated you so that you wrote an
    incomplete post that focused on your ire.

    If you look at Framework Design Guidelines (Cwalina and Abrams) they dedicate 25 pages to how to work with exceptions. In which they stress don’t swallow exceptions. I take your blog post for what it is. A rant about something that caused you to loose time and productivity while trying to get your work done.

    IMHO, it is possible for the code to use “try { … } catch (Exception ex) { … }” effectively. However this is only the case if the code is API code and you truly only care that a problem occurred and not what the actual problem was. The difference is that there MUST be code in the exception handler. Most likely this would be wrapping the inner exception and throwing it as an exception specific to the API that makes sense in the context of the call. So that you can throw a WidgetSaveException instead of a ArithmeticException or FileNotFoundException from a method that is supposed to be saving something to a database. However, you might want to look at that method more closely as it is probably trying to do too much and could benefit from some refactoring so that you know the exact exceptions your code can throw.

    I do disagree with your comment that you should let your global exception handler do most of the work. It is a better practice to do what you can as close to where the exception occurred as possible. If it is a fatal error and you want to save data your global handler most likely will not have access to the components needed to save the data. Plus, this could be more problematic if the save is what caused the exception that ended up in the global exception handler. As Jim Danby stated you don’t want to have customers lose faith in your product. Any developer needs to work hard to make sure that fatal exceptions are pretty. I would hope that my customer never see the framework provided exception handler as that means something went horribly horribly wrong.

  26. I will usually capture exceptions specifically in service calls that return json. this way I can

    return new {
    error: {
    message: ex.Message,
    debug: IsDebugMode ? ex.ToString() : null
    }
    }

    Other than service calls, I’ll let the global.asax handler do the error handling. In a service call it can break a lot of the client-side code to have a generic html error page as the result.

  27. karl says:

    We’re all agreeing, except for the title – which was meant to be sensational more than anything. I even say its ok to catch exception when you understand the implications.

    My point was that a lot of developer use try/catch as though it was an if statement, which is the wrong extreme to start off with.

  28. Vibhuti Ranjan Singh says:

    Nice article, agree with the approach, exception suppressed leaves application unstable and unpredictable

  29. Ben says:

    Personally I use:
    try/catch,
    display a friendly custom error page,
    and the exception handling application block to log errors in Event Log.

    It honestly makes no sense to me to not use try catch in a high quality app.

  30. Harry M says:

    As everyone else is saying, its normal and OK to use …}catch(SomeExceptionIThinkMightHappenAndIKnowHowToDealWith ex){…

    A ‘rule’ isn’t needed. All that’s needed is to understand that stuff goes horribly wrong if you swallow exceptions.

    @Stuart catching and logging is OK as long as you’re logging EXTRA info. Don’t do this! http://stackoverflow.com/questions/95547/should-i-catch-exceptions-only-to-log-them

  31. Seth Petry-Johnson says:

    I have to agree with Kev… the title of your post is “Don’t Use Try/Catch”, but the point you’re actually making is “don’t swallow exceptions” or “use exception handling properly”.

    If your app can recover from an exception, and the exception is truly “exceptional” and not part of the common case, write a handler for it.

    If an exception isn’t the end of the world, and there is a specific reason that the exception can be safely ignored, then swallow it BUT COMMENT THE CODE ACCORDINGLY.

    If your app can’t recover from an exception, let it bubble up to a global handler to log it.

    I am 100% against abuse of exception handling code, but I’m also 100% against the verbatim statement “don’t use try/catch”.

  32. D. Lambert says:

    My understanding has always been that catching a specific exception (when expected) and dealing with that exception is correct. To echo Stuart (and others), is the real rant here against catch blocks that swallow indiscriminately?

  33. karl says:

    Jim:
    Web and desktop are different beasts. A unit of work on the web tends to be very small, so lost data is minimal. Nevertheless, it ought to be possible to let the exception bubble all the way up and still allow users to try and perform some last-minute action.

    bryan
    That kinda thing can be done in a global exception handler, with the added advantage that its easier to change the behavior in the future.

  34. bryan says:

    I like to use try/catch blocks to give exceptions a more friendly description that describes what happened in plain language. I also make sure to pass in the original exception object as the inner exception thus preserving it for use in debugging. Also, should you really allow an exception caused by a user failing to fill out a required field bubble up into a global exception handler or should you catch it and display a message to the user indicating what they did wrong? I’m inclined to think the latter.

  35. Jim Danby says:

    No no no no no.

    Yes, it is bad to just swallow exceptions. No, it is not bad to try to handle exceptions, even unexpected ones. Your suggestion harks back to the bad old days of Windows. I remember too often working in an application like Word and having an exception occur that crashed the application and threw away my work. I would much rather see, let’s say “Out of memory” and at least be able to attempt to sabe my work. Your approach means the potential for users to lose data. Do that and you lose customers and fiath in your product.

  36. The Corollary to this rule is “don’t throw exceptions for unexceptional behavior”. It’s even more annoying to have to write essentially swallowing try/catch blocks because the library you call uses exceptions to signal certain not uncommon outcomes.

  37. Good article, although I agree that the title is a little misleading. There are some cases where exception handling is useful. However, I completely agree that an empty catch is always a bad idea.

    Catching specific exceptions is great and logging additional information before re-throwing the exception is even better. More information is always useful during debugging.

  38. D0cNet says:

    Good article. Developers should properly handle exceptions and know what they are catching.

  39. Mike says:

    Good post! I would rather have a system hard crash and stop and have to explain that to a customer than have a system take some sort of unforseen plot twist and so something incredibly wacky and have to explain that.

  40. Same problem in the Ruby world.

    rescue nil

    It's the equivalent of the empty catch.

  41. Rob says:

    Totally agree. Can’t stand empty catches. I think R# marks them as something bad, or we have something set that does so for us.

    If you don’t plan on handling an exception, then you shouldn’t really be catching it, or you’ve not written the code correctly (if/else instead?)

    Nice little regex to hunt those buggers down:

    catch:Wh*\{:Wh*\}

  42. Kev says:

    Karl….I think the title is bit misleading and suggests you should never use try/catch.

    Shouldn’t it be “Don’t swallow and hide exceptions”?