Living with unchecked exceptions

Hey there fabulous readers: I’d like to get your opinions on unchecked exceptions.

Before you run off down to the comments and start typing a short novel, I want to make sure that we’re all on the same page here.

To start with: “checked exceptions” is the feature perhaps best known in Java whereby a method M must state which exceptions it may throw. If method N calls method M then either N must handle those exceptions or it must state that it can also throw them, and so on. Basically it makes exceptions an explicit part of the contract of a method, right up there with its formal parameter types, return type, and so on.

// Java
private void someMethod() throws SomeException
{ ... }

This is a somewhat controversial feature of Java. Opinions vary widely as far as whether the feature achieves its design goals effectively or actually creates more problems than it solves. The original designers of C# rejected checked exceptions and haven’t much regretted it; you can read Anders’ thoughts on it here.

My goal here is not to rehash that debate; there is approximately zero chance that this feature is going to be added to C# now, so advocating for or against that position is not a good use of your time. Rather, I want to talk about the fact that C# has had unchecked exceptions this past decade, and somehow people must have adapted to the fact that the set of exceptions a method may throw cannot be determined from the method signature. My questions for you are:

1) Have your programs had bugs that you fixed by adding exception handling for a specific exception that you did not realize could be thrown?

2) When you are writing new code that calls methods you didn’t write, how do you know what exceptions you should be handling? Are there particular exceptions that you believe should always be handled regardless of what method produces them? For example, is it the case that any method that can possibly throw IOException should always be inside a try-catch?

3) How much weight do you give to consistency of exception handling? For example, if you are writing new code to call a method M, and nine times out of ten elsewhere in your program the call sites for M wraps the call with a try catch that catches FooException, do you see that as a good reason to catch the same exception in the new code? Or is that a false generalization?

Please leave any thoughts in the comments; I’ll follow up with a summary of responses in a later episode. Thanks!

83 thoughts on “Living with unchecked exceptions

  1. The number of “catch” in my code is… very small. “finally” is very useful; “catch”… not so much. The number of times when you can *usefully* compensate for something is very small – in fact, most of my “catch” are just “log to the debug console and rethrow” – or at least, the “catch” is the same no matter what happened. So in virtually all cases, it doesn’t matter *what* exceptional thing happened: I am going to react the same, and I don’t need checked exceptions for that.

    There are a *very few* set of scenarios where the exact exception matters, and for those few, you usually know the exact exception types (or at least, what they smell like) in advance.

  2. I don’t mind unchecked exceptions. I can see why checked exceptions would be nice and crisp to have, but it doesn’t appear to give me any grief that they aren’t there.

    In my software no exception should ever go unhandled (of course they sometimes do, but I consider such an oversight a bug). Nothing that makes my apps crash could possibly be good, no matter what your angle is.

    I often don’t know which specific exceptions I should be handling, but by the time the exception reaches the outer layers of code I usually apply the Pokemon exception handling paradigm. I am aware that I can often be more accurate in terms of which exceptions I should specifically catch, but even my sledgehammer approach doesn’t seem to cause many problems for users, if any at all.

  3. 1) No, I’m pretty sure not

    2) If it’s a .NET framework method I (might) check MSDN. In order cases I’d check (again, might…) any available documentation or the source code (if available). However most of the time my expectation is that an exception thrown means that an unrecoverable problem has happened, and the best place for that exception to go is back up the call stack. That said, this rule does not necessarily apply when I’m calling a method that I know (directly or indirectly) calls an external resource such as a file system, database or remote service.

    3) Lots! In general this means that, at the top of the call stack, I catch and log all exceptions. Or, when I’m adding a method to an existing codebase I can confidently not worry about exception handling in that method, because I know that any exceptions will be logged elsewhere. However, in your FooException I typically would be consistent with existing calling code, and catch the exception. Or, I would not catch it and I’d refactor (with discussion within the team) the existing code to match the code I was adding.

    The above is based on the assumption and expectation that exceptions are used only for “exceptional” (i.e. “it’s broken, and there’s nothing much you can do other than log and error and/or show an error message to the user) scenarios.

  4. Exception handling should occur only when you can deal (and react) with the exception, so not every method that can thow an exception should be wrapped in a try-catch block.

    All the exceptions that a method could throw should be documented by the /// , but the ultimate discovery tool is Reflector (or something similar)

  5. 1) Yes, often.
    In the code base I’m working with, it’s not uncommon that we only handle IOException when opening a file… and forget about UnauthorizedAccessException.

    2) Not all IOExceptions need to be handled… when opening files that are supposed to be installed with the application, any error accessing those files is fatal, and the exception should stay unhandled (in Java, I’d rethrow it wrapped in a RuntimeException). For other files, IOExceptions must be handled properly.

    3) I think this is a good generalization for the most part, even though this doesn’t quite fit with my answer to the previous question. But in the couple of cases where I don’t need to handle the IOException, I would be OK with a tool forcing me to wrap it in a different exception type.

    IMHO, the main problem with checked exception handling in Java is with code patterns where an exception passes from code in class A through a method M in a separate component B, back to class A where it should be handled.
    This happens with functional-style code using callbacks, with the visitor pattern, and probably many other cases as well. In this case, the method B.M() needs to be polymorphic w.r.t. the exception types thrown: it throws the same set of exceptions as the callback method used.
    This can be expressed in Java’s type system using generics: ” void M(…) throws E”, but actually going this way can quickly lead to extremely verbose code. And it doesn’t help that you can’t use “catch E” due to type erasure. (for example, this would be necessary to transport checked exceptions from one thread to another)
    The new functional interfaces in Java 8 seem to assume that you don’t use checked exceptions.

  6. The answers to these questions vary based on application. For example, I’m much pickier about exception handling in military-grade software, and typically elide exception handling on throwaway projects.

    “1) Have your programs had bugs that you fixed by adding exception handling for a specific exception that you did not realize could be thrown?”

    Yes. Sorry, I don’t remember what it was, but I definitely remember this happening.

    “2) When you are writing new code that calls methods you didn’t write, how do you know what exceptions you should be handling? Are there particular exceptions that you believe should always be handled regardless of what method produces them? For example, is it the case that any method that can possibly throw IOException should always be inside a try-catch?”

    Thankfully, .NET’s one-framework-to-rule-them-all handles most of this. I rarely make function calls to things other than .NET framework code or code developed in-house. The framework code developed by Microsoft is meticulously documented with possible exceptions and I have a high level of confidence in the software and its documentation.

    When making calls to a third-party library, I trust nothing. I don’t recall using any third-party libraries that document possible exceptions, and I wouldn’t believe them if they did say. During development and testing, common exceptions will get teased out and I’ll add proper handling for those. I try to handle these cases as generically as possible, since anything we can’t handle I make sure to fail fast.

    So, in short: Trial and error.

    “3) How much weight do you give to consistency of exception handling? For example, if you are writing new code to call a method M, and nine times out of ten elsewhere in your program the call sites for M wraps the call with a try catch that catches FooException, do you see that as a good reason to catch the same exception in the new code? Or is that a false generalization?”

    Zero. It is never sufficient reason to add exception handling without further understanding. Inconsistent exception handling is, of course, strong evidence to understand how the exception occurred, and consider whether it is relevant in the inconsistent method call. Consistent exception handling is also strong evidence to consider refactoring the nine cases of repeated code into its own method.

  7. 1) Occasionally: I have improved database programs by retrying queries that were chosen as a deadlock victim for example. But note that this wasn’t an exception of a specific type – it was one of a specific type with a specific error code. So the signature would not have helped.

    2) When writing new code I treat all exceptions alike until experience shows that some should be treated differently. At that point it’s obvious which ones they are, as they’ve been thrown by the library code in use. I can’t think of any exceptions that I always try to catch straight away, but other contexts might require that.

    3) I would not require consistency of exception handling. If I saw that FooException was always being handled elsewhere in the code, I’d try to understand why, and see if that reason applied in the current cirucmstance. But I’d also ask myself why the call and its error handler were not themselves wrapped in some method that would save writing the try-catch every time. Only if handling was necessary, and the common method was impractical would I then use try-catch. (You can imagine that the rest of the application could crash if FooException was not handled every time, in which case I might be forced into handling it, against my better judgement.)

  8. The biggest limitations I see with exception handling in general stem from the fact that way too much information is encapsulated in the type of an exception, and the fact that languages have insufficient support for what should probably be the two most common exception-processing patterns: performing some action in response to a condition that cannot possibly resolved thereby, and marking exceptions which indicate circumstances other than what their types would imply.

    An example of the former situation would be code which acquires a lock and starts modifying the locked resource when an unexpected exception is thrown. Even if the code has no expectation of being able to handle the exception, it should still take action as a consequence of it, *explicitly invalidating* the locked resource before releasing the lock, so that pending or future attempts to acquire the lock will immediately fail rather than remaining blocked forever. While it might be possible to achieve similar semantics by having code set an `IsInvalid` flag before beginning modification and clearing it afterward, such a manual approach would leave many opportunities for bugs which could be avoided with a variation of `using` which would call `IDisposableEx.Dispose(Exception Ex)` [Ex being null when no exception was pending] if defined. Further, the aforementioned style of `using` could also allow code which tries to use a corrupted object to record the circumstances of its corruption–much more useful than the mere fact that `IsInvalid` had been set but not cleared.

    With regard to the second point, the fact that Foo which can throw an exception of some type does not mean that any exception of that type thrown by a nested method call to Bar would have the meaning expected by Foo’s caller. Checked exceptions would be useful if, rather than having checked-ness be a characteristic of exception types, “expected-ness” was a characteristic of exception instances. A “catch-expected” statement should only catch exceptions which were thrown by a “throw-expected” statement *and have not percolated up through any layers where they were unexpected*.

    I know you have written a few times that programs should only catch things they can handle; one difficulty with that given the present exception-handling practices is that there are many situations where 99% of the things that could go wrong should be handled the same way, whether or not the exact conditions represented thereby were expected, and even those which cannot may not be identifiable by their exception types. For example, 99% of cases where a `LoadDocument` method throws a `DivideByZeroException` may best be “handled” by abandoning partially-constructed objects and indicating that the file isn’t readable; an abrupt shutdown may needlessly corrupt other files. On the other hand, in some cases where an unexpected `DivideByZeroException` might cause an incomplete update to a shared data structure (leaving it in a corrupt state) an abrupt shutdown may cause less harm than would continued operation. What should matter to the calling method is not the type of the exception, but rather whether it has corrupted anything beyond those objects which are being abandoned. Making it easier for code to invalidate objects whose update methods exit abruptly would increase the reliability with which caller code could know how to properly handle such conditions.

  9. I practice a defensive functional style in C# generally and throwing exceptions is the easiest way for me to write unit tests that ensure constraints are honoured. I like my code to stop the moment something unexpected occurs. The problem with checked exceptions is that they don’t trust I know what I’m doing. 99% of the time I’ll just use the catch block to log the exception which is what would have happened if the exception was unhandled anyways. The much bigger problem is that in Java when engineers are under serious time constraints the engineer might just stick in an empty catch block which can destroy the maintainability of a codebase over time. So it’s a really good thing C# doesn’t have them in my opinion.

  10. I’ve also been tricked by opening a file and only catching IOException. I think the difficulty there is that if you want to catch exceptions that aren’t your fault, but allow through stuff like ArgumentNullException, there’s no single exception class you can catch, so it’s particularly easy to slip and do it wrong.

  11. Thrown exceptions are part of a method’s type, in a sense, if you think of them as a different sort of return value. As such, people deal with unchecked exceptions in C# in essentially the same way people deal with types in general in non-static-typed languages. You could formulate very similar questions for dealing with dynamic types and get very similar answers to what you’ll get here.

    The main difference is that the cost-benefit ratio of dealing with checked exceptions is vastly less favorable than the cost-benefit ratio of dealing with what C# actually considers the “type” of a method.

  12. Why do you set a font weight of 300 in your css.

    The result is a very thin, pale, unreadable font rendering on your pages that make them less accessible to a wider audience.

  13. 1. Bugs?

    I guess that depends on the definition of “bug”, as opposed to simply “unexpected failure”. But in the sense that I have had to add exception handling to code because I did not realize a particular exception could be thrown, yes…I’ve had to do that.

    2.How do you know the exceptions? Are there exceptions that should always be handled?

    As others have mentioned, I rely on MSDN and XML comments for other libraries (which are of course not always comprehensive). Sometimes, you find out just because the program crashed or caught an exception higher up.

    I can’t think of a single exception that I think should _always_ be handled, specifically. As mentioned, one handles an exception when one can actually do something useful in the handler.

    Now, most of my code winds up with a top-level exception handler somewhere. But often this is simply a handler that reports/logs the exception and then exits the process. This provides a somewhat better user experience (albeit still a substandard one), since at least Windows doesn’t go through its “attach a debugger? close? report?” routine.

    3. Is consistency important?

    Yes. Consistency is of great importance in a field like programming. However, that does not mean one must _always_ do the same thing in every place of the code. But one should do something different for a given exception only when there’s a known good reason for it.

    Note that it’s less about _whether_ to catch the exception (since that’s driven by whether it’s feasible to recover from the exception), and more about what one actually does with the exception (i.e. there’s value in being consistent here, but there’s always the possibility of extenuating circumstances).

  14. Some libraries, such as Int32.Parse, use an exception as an essential part of the interface.

    I use a library to open a type of data file and it documents that.. “If an exception of class XYZ is thrown, this means that the input file is malformed and retrying would give the same result. Other exceptions are signs of other errors and it may be worth scheduling a retry.” (Think difference between HTTP 4xx and 5xx errors.)

    This sort of nuance would only be found in English documentation. Having a formal annotation inside the DLL that this function might throw XYZ without saying what it means wouldn’t really help me at all.

  15. I tend to try and catch specific exceptions that I generally expected to see and can handle – e.g. a FileNotFoundException and that report that back or bypass something. Exceptions thrown due to restrictive permissions on a File for example I wouldn’t catch as it’s generally a setup/one off issue that once resolved won’t appear again.

    It is quite difficult catching the correct ones, generally it comes from knowledge of the framework or a quick check on MSDN. I have indeed fixed code by adding an additional specific catch that was missing.

    Unfortunately the most common thing I see in code is a catch ALL exceptions which I don’t agree with.

  16. 1) Yes, they tend to come out in the wash in unit testing and QA. Rarely on live software, but it does happen

    2) If it’s not framework code I don’t trust the docs, I make the code fail in a way I’d expect and then catch that exception.

    3) None . . . or some, depends. Either M should be wrapped removing duplicate code, or the call made safer, or FooException needs to be handled on a case by case basis

    But generally we don’t catch exceptions.
    Scenario 1. Say we’re providing an api over some code that internally calls a dictionary. We may catch “Key not found” exceptions to wrap them in our own exceptions, or just throw our own exception and not expose the Key not found.
    Scenario 2. We have top pokemon exception handlers that log messages. In a service that’s consuming messages from a queue we wouldn’t catch every possible queue / SQL timeout / deadlock exception. We’d trust the stack to unwind properly, rolling back where appropiate and have the exception logged and forwarded to us. 99% of the time (or more) it’s bad transactionaly data, corrupt files etc.

    (Disclaimer, I’ve never coded Java in anger)
    In all honesty I can only see how checked exceptions would get in my way, can’t see any real world benefits, but I am sitting on the edge and have no experience to back this up. C# ftw!

  17. It may just be an artifact of how I design things or the kinds of programs I’ve been hired to write, but I’ve found try {} catch (Exception e){} to work for my needs in the gross majority of cases. It is rare that I need to handle different kinds of exceptions differently. This is doubly true for non-Framework code where quality documentation is rarely given a high priority.

    Mostly I rewrite the code so that exceptions aren’t thrown in the first place or are so severe that the task I’m trying to do won’t ever succeed (play a corrupted audio file) or indicative that the computer itself is broken. In the prior case, log it, move on; in the latter case, crash (I don’t work on software where working on partially functioning hardware is a reasonable requirement).

  18. 1) Definitely. My blog post “Exceptions thrown by BitmapImage and BitmapFrame” (http://code.logos.com/blog/2010/07/exceptions_thrown_by_bitmapimage_and_bitmapframe.html) covers eight different exception types that BitmapImage.EndInit or BitmapFrame.Create (in WPF) can throw. The current version of that code actually catches *eleven* different exception types, each documented with a specific failure case. (We just don’t like “catch Exception”.)

    2) As another commenter wrote, trial and error. Mainly we add exception handling based on post-mortem crash reports (which is perhaps the worst possible way). The .NET Framework is reasonably well-documented in terms of the exceptions it can throw, but mono’s versions of Framework methods can often be different. And MSDN’s documentation is definitely not complete; did you know that HttpWebResponse.GetResponseStream can throw an InvalidDataException when AutomaticDecompression is enabled, and the GZip header is corrupt? I didn’t. Third-party libraries are consistently a surprise and sometimes change thrown exception types from version to version; we often have facades that wrap them just to standardise exceptions.

    3) It’s hard to answer yes or no for this question. FormatException is a great example: in some cases, you’re parsing user input and catching FormatException is the right way to handle failure to parse an individual string. But sometimes you’re parsing a machine-generated file, and it is your expectation that no deserialization should ever fail, or, if it does, you recover by abandoning the entire file, not catching the exception at the individual string level. So half the usages of int.Parse (bad example, because you should use int.TryParse, but bear with me) would catch FormatException, and the other half would assume it wouldn’t fail/let it be handled much higher up the stack. I think more context than “most other methods catch FooException from method M” is necessary to know whether the exception should be caught. I also agree with another commenter that catching an exception in 9 out of 10 methods may be a sign that (repeated) exception-handling logic needs to be refactored into a helper method.

  19. 1. Yes, especially when dealing with some rare staff like network or xml
    2. I start with a catch block that catches Exception, logs it and then does throw; then I emulate sad paths and see what kind of exceptions are thrown and catch them. No, if your current level does not need to care about all level of exception, only the one that you can handle. If something really goes wrong – you should catch it in the topmost level and just fail the hole operation with rolling back the transaction, rather than trying to restore the state and carry on.
    3. As I have said above – it depends on the code you write. If 9/10 time previously you have tried to reconnect if a connection failed, the 10th time you might have lost the session and reconnecting is not an option.

  20. > 1) Have your programs had bugs that you fixed by adding exception handling for a specific exception that you did not realize could be thrown?

    I can find no examples where this has happened.

    >2) When you are writing new code that calls methods you didn’t write, how do you know what exceptions you should be handling?

    I review the documentation for the method. For each exception listed I consider whether I can guarantee that the exception cannot happen. For those in which such a guarantee cannot be made, I consider the consequences to my program when it happens. Then I decide whether it makes sense to handle that exception. Exceedingly few exceptions satisfy this condition.

    >Are there particular exceptions that you believe should always be handled regardless of what method produces them? For example, is it the case that any method that can possibly throw IOException should always be inside a try-catch?

    Many of the programs that I have been writing lately are non-interactive. When an exception of any type occurs, the code just cleans up everything, logs the details of the exception, and bails. For these types of programs, IO exceptions are given no special treatment. Based on this experience, I can think of no types of exceptions that should always be caught.

    > 3) How much weight do you give to consistency of exception handling? For example, if you are writing new code to call a method M, and nine times out of ten elsewhere in your program the call sites for M wraps the call with a try catch that catches FooException, do you see that as a good reason to catch the same exception in the new code? Or is that a false generalization?

    I give no weight at all to that. I treat each case as unique. It is almost never the case that I would catch an exception near the call site of the method which produces the exception. The handling of exceptions that cannot be avoided is normally part of the larger process, and occurs several steps up the call stack. So the information about what exceptions are being caught is not readily available. But even if it were, I would still go back to the documentation and consider each exception listed individually.

  21. 1) Yes, but just once. When I was starting out in C#, I was coming from a Java background, which had trained me to write “catch (SpecificException)”. After getting a bug report that an exception was thrown that I wasn’t catching, I then switched to writing “catch (Exception)”. That’s an anti-pattern in Java, but it seems necessary in .Net.

    2) Microsoft is good about documenting which exceptions can be thrown, but a lot of code either doesn’t take into account methods that it calls (e.g., a method documented as only throwing FooException, but it calls File I/O stuff that can throw IOException), or it doesn’t document it at all. Therefore, “I don’t know which exceptions will be thrown” is the more common answer, and I write “catch (Exception)”.

    Between #1 and #2, I’ve now been trained to write “catch (Exception)” any time I catch anything. (try-finally is obviously more common than try-catch.)

    3) I think consistency on a per-API basis is more important: For a given API, I would expect consistency: Either all calls are in an immediate try-catch, or all calls are not, and a higher-level try-catch will handle it. For example, I may want to catch network communication exceptions at the lowest level, but disk i/o exceptions should propagate up, even though they’re both IOException.

    I wouldn’t want to require try-catch blocks based on a generic built-in exception type (e.g., FormatException is reused by many, many libraries), but for a custom exception type, it might be OK.

  22. My biggest problem with C# exceptions is the “organization” (or rather, lack thereof) of the exception classes. There’s this obvious “ApplicationException” that all application exceptions SHOULD derive from… but you’re warned away from doing that. All things that aren’t “ApplicationExceptions” SHOULD be system exceptions that shouldn’t be caught or handled (like OutOfMemory exceptions).

    Seriously, it’s such a confusing mess, that lazy developers just always catch “Exception” because they have no other common root to catch what they want. And there’s no way to tell what exceptions a given method throws (even .Net framework APIs aren’t well documented… some are, some aren’t, it’s hit and miss).

    I think if more thought and planning and design had gone into the creation of all the framework exception classes, things would have been a lot better over-all. But that’s unfortunately water under the bridge now.

  23. When writing server code I follow the school of thought that says “crash early with logs and then restart”, that plus transactions (e.g., transactional queues) is best.

    Application code is harder and I have no consistent strategy that works well enough to call it a rule. I am reading everyone’s comments here with great interest.

    There are some C# changes that could help any exception strategy though. (Besides implementing checked exceptions, which, when programming in Java, I definitely didn’t like.)

    a) Provide destructuring assignment for tuples AND for anonymous types. The Framework doesn’t really need it in too many places, but there are other libraries and user-written code that could use multiple-return values rather than exceptions for the situation where you CAN recover – the tricky cases where whether the “error” is an exception or acceptable behavior is context dependent. (Destructuring assignment would also help get rid of uses of out and ref parameters, good riddance.)

    b) Allow multiple different exception to be caught in a single catch, e.g., “catch (ArgumentException|DivideByZeroException ex) { … }”.

    c) Promote AggregateException to a first-class feature of the language. Allow catch clauses to look inside of AggregateExceptions somehow, possibly with special syntax. Make using statements wrap exceptions that occur in the compiler-generated finally clause in an AggregateException with the exception that the finally clause is handling. Other possibilities exist.

    d) Provide a static analysis tool, in VS, that traces exceptions and reports on all possible exceptions you could get (modulo threading) from a given call. Provide the output for the Framework and encourage library authors to provide it for their libraries. (Maybe such a tool exists, in or out of VS, and I’m not aware of it? But nobody has mentioned it here …)

    • (b) Would be a great idea, you can then group the handling together. A few other people a mentioned this, and then saying the end up with the ‘catch (Exception) {}’ to cater for it.

    • I would also like (b). It would work around some of my complaints about the class hierarchy of exceptions. I have had to catch Exception and check the real type manually more often that I would like.

  24. On the specific question “Have your programs had bugs that you fixed by adding exception handling for a specific exception that you did not realize could be thrown” – change “bugs that you fixed” to “behavior that you improved” and the answer is yes.

    Sometimes you discover that a particular exception is thrown that does indicate a recoverable error – so you can catch it specifically and write recovery code of some kind (rather than just fail).

    Sometimes Framework code that implements network operations (sending email, talking to servers/services) is like this. You discover, on reading logs, that you caught a specific subclass – that you weren’t aware of an exception – that signals a specific condition that you can now differentiate from others..

  25. 1. Yes, and typically it annoys the stuffing out of me when this is a result of poor documentation — i.e. code throwing ArgumentOutOfRangeException when it’s only documented to throw FormatException, stuff like that — even when I think I’m handling the error, I still lose. Double points are deducted for when the exception is overly specific (multiple types for cases you typically would not be interested in distinguishing) and there’s no base type.

    2. I read the documentation. If there is no documentation, I can’t catch any exceptions, so that’s simple. Well, more realistically, I’ll try to figure out what it does throw by arranging for it to fail, if the failure scenario is sufficiently obvious, but if not I don’t sweat it. I have seen code fail harder on erroneously catching exceptions when the error could not be handled than I’ve seen code fail on not handling an error when it could have.

    Should all IOExceptions be caught? No, only those you can handle. However, it is true that almost all IOExceptions *can* be handled, even if it’s just to rethrow it as “high-level operation X failed because of low-level I/O error Y, and now we shall crash”. A bare IOException is usually very uninformative, even with full stack trace included. Like NullReferenceException, you want to avoid your code actually crashing on one of these and (if need be) have it crash on something higher level instead (ArgumentNullException, InvalidOperationException).

    3. I demand consistency in exception handling, that is to say, I insist there be none unless you’re demonstrating a clear need for handling the error and a clear strategy for doing so. If FooException is caught everywhere, that raises a big red flag that either throwing FooException is not a good way of doing business, or the current code is too low level and should wrap around a simpler core that reduces the catch blocks. In no case would I be tempted to go “well it’s caught all the time, so let’s catch it here too for old time’s sake”.

    The only thing I always make sure exists is a top-level handler, and even that doesn’t handle, it just logs (ApplicationDomain.UnhandledException). I do work on back-end stuff mostly; for front-ends and web services you may want something slightly more dignified that at least always gives a usable response to the outside.

  26. 1) I’m not aware of such case.

    2) I don’t know. We have distributed software communicating asynchronously, so we generally catch Exception, write exception to log and send it back to caller in case of back-end component or show error to user if exception is received on front-end side.

    3) Same as in 2) Catch clause with something other then Exception is very rare.

    In our experience there is very small number of cases when we can recover from exception. Most of the time exceptions are logged and/or reported to user/management console.

  27. 1) Yes, it sometimes happened.

    2) Can’t think of any such case right now.

    3) I think this isn’t going to answer your original question, but here: I think that if nine times out of ten I wrap calls to M() with the same try-catch, then I should already have written a TryM() wrapper that does the try-catch and has the sensible return type that M() should have provided in the first place.

  28. Exceptions should only be handled in cases where they might leak outside of the system. Eg. to the client of the system. And you should generally catch Exception. If you are adding specific catch clause for specific exception type over specific method, you are most probably doing something wrong. You do not catch FileNotFoundException. You first check if file exists and then open it. And if that throws, then there is absolutely nothing your code can do about race condition like this. If you need to do that, then the called method is not properly designed.

    To answer the questions:
    1. No
    2. There should be absolutely no need for that. You either catch Exception around your application’s boundary or you don’t catch anything.
    3. Big consistency. Exceptions are handled only on system’s boundary and nowhere else.

  29. 1. I can’t think of any.

    2. You don’t (unless it’s explicitly documented somewhere), and I’d say that, in general, it’s a bad idea to try and do this. Just because some code throws a FooException today doesn’t mean that it will tomorrow. And in practice, it’s virtually impossible to figure out all the exceptions it might throw and you should handle. Catching specific exceptions is really a dangerous game. Even if you think you’ve got them all, what exceptions might show up in the field?

    3. None. In general, I tend to think that code with lots of try/catches is poorly written (especially when the catches are for specific exceptions).

    I think the whole notion of “handling” exceptions is a bit of a fool’s game. I can probably count on the fingers of one hand the times where I’ve been able to catch a specific exception and then do something intelligent with it. 99% of the time you should either catch everything or catch nothing. When an exception of any type occurs, rewind to a stable state and then either abort or continue.

  30. 1) Definitely. Granted, these are generally corner cases, but it has happened.

    2) There is a strong reliance on both documentation and runtime behavior. Third party documentation seems to vary widely in terms of quality and descriptiveness, generally erring on the poor side, but the most common exceptions tend to be what’s most documented.

    For example, imaginary method Frob(int number) will throw an ArgumentOutOfRangeException when given numbers below 1000. It will also throw an OverflowException if the value provided overflows doing calculations. The first exception is likely to be documented more carefully, and likely to be handled more carefully because it describes a general case that the user may run into more often. The second is much less likely to be documented, but also less likely to be encountered. By the same token, it’s also less likely that a developer will be able to do anything useful with it specifically besides log it like all of the other exceptions and check for that case in a bug fix.

    As for whether a specific exception is always handled, and given how many custom exceptions abound, I’m going to stick to the framework methods here. There may be a few that occur more often, but for the most part I think they are largely situational. If I need to specifically watch for an IOException, it’s because I’m working with a situation where recovering from IO difficulties is crucial. In that case, I will likely already know that it’s a case that should be recovered from. Other times, it may just mean that I can’t use that particular thing for IO in that way, log it for inspection later, and move on.

    3) It depends. If the catch block in all of those situations are essentially performing the same task, that’s a code smell for copy/paste duplication. In that case, I would rather consolidate exception handling, if possible, to avoid perpetuating this extra bloat to the code. On the other hand, if the catch blocks are all doing something different, it becomes a largely situational thing where it might be useful to handle but it might also be just as useful to be handled elsewhere.

  31. It depends on the quality of framework. In ASP.NET development, MSDN helps a lot: it is nearly always clear and understandable why and where an exception may be thrown. Fixes usually don’t lie in catching exceptions but rather involve preventing them long ahead. Furthermore, as has already been noted here, catch statements are often about logging and re-throwing.

    In stark contrast to this, Windows Phone 7 development is about hours and hours of figuring out why the app crashes. An app supposedly has everything done right, yet all of a sudden COMException, or even worse an Exception, is randomly thrown. These exceptions do not tell where to look at, they are not OutOfMemoryExceptions nor IOExceptions, etc., so that a developer is left in frustration, searching the net and hoping that somebody must have already shared experience about that particular situation. MSDN does not indicate which methods throw which exceptions at all. The debugging comes to a step before finding out what went wrong and a surprising SEHException appears, so that you need to start over. Fixes are often about catching exceptions. Fortunately, Windows RT development feels quite better, though the platform seems to be still far less dependable when compared to such frameworks as WPF and ASP.NET.

    Personally I find helpful the silent approach of browsers towards JavaScript execution problems, whereby the browser doesn’t halt all JS when some of it fails, it just stops one execution branch. Of course, the app ends up with an inconsistent state, but on the client-side it might actually make sense: the app feels resilient and almost never crashes entirely.

    • 1) Yes, mostly in Windows Phone/Windows RT development. Probably there were such cases on the server-side as well, but that happened far more rarely and was related to interop and complicated things like ThreadAbortException.

      2) It seems like in .NET, it is impossible to know for sure anyway. Some frameworks provide useful documentation on this matter, so that you can infer realistic cases that need to be tested. I prefer writing integration tests (i.e. unit tests with slightly less mockery or without any at all) that would expose to which exceptions the code is practically vulnerable. If a catch statement is deemed necessary it is a good idea to have its body covered by a test because otherwise there is no guarantee that the catch statement would not actually worsen the situation after an exception.

      3) If there is a situation that a method call consistently needs a catch statement on every call site, there might be some space for improvement in the program’s design. I would prefer wrapping the throwing class around into a safer utility that would handle the exception. Otherwise, there would be copy/pasted catch statements all around the project. The problems would worsen if in the next library’s version the method M would start throwing a new exception BarException, so that everywhere the M is called you would need to add another one catch block. So probably a wrapper is preferable — call the troublesome M() only in one place in the project.

  32. I don’t know how to give a direct answear to those three questions, I think the entire exception handling thing is very bad designed, not just a matter of checked vs unchecked exception.

    I have read your article about the four kinds of exceptions and partly agrre with it, in fact, I have changed a bit my style after reading it, in the end I almost never use “catch” (but almost always have a global exception handler to log), if the exception is, for example, DivisionByZero it shouldn’t be thrown to start with, so, if not supposed to be thrown why catch? But I think you are more interested in exceptions like IOException here, now the poor design issue, when I try to catch na IOException, GDIException, SqlException, etc, many times the message is like “General Error”, “Unspecified Error”, etc, great, how am I supposed to handle this? Or the exception have na extra property with a number, wich I can look up from a really big list of errors most of wich impossible in my case, does anyone expects me to write code to handle each of those errors? In most cases I have a code wich may throw one of those exceptions I don’t know what to do if it throws an exception, if I don’t know to handle it I simple don’t catch it, and, often, when there is a specific situation I know how to handle there is no easy way to identify this situation.

    Once I have used a Redgate tool to find what exceptions my code may possble throw, in a particular method it could throw na IOException, wich was weird since it had no IO at all, after some diging I found that it called int.Parse, wich is not documented to throw IOExceptions either but in its parameter validation it uses a helper method to read resources wich may throw a IOException, though I never saw this happening, eve for simple methods that tool pointed at 16 exceptions or so, wich made the tool pretty useless, after all this:
    1) Yes, as weird as it may sound;
    2a) Documentation;
    2b) And do what in the handler? I don’t think it makes sense to handle na exception if I don’t know what to do with it;
    3) A false generalization, if, for any reason, a particular method throws an exception that should always be handled the same way why doesn’t this particular method handle the exception itself?

  33. Unchecked exceptions have never bothered me much; usually, a failure is a failure. β€œcatch Exception” is a much bigger issue. On the one hand we have lots of Microsoft books and articles that say β€œnever catch Exception,” but on the other hand I have seen Microsoft examples and code that do just that. I cringe every time I write β€œcatch Exception” but I don’t know what else to do. Is it too late for a new β€œsafecatch” keyword that ignores OOM and ThreadAbort?

    • UPDATE: A previous version of this comment contained an error. I said: OutOfMemoryException and other super-fatal exceptions can be caught but are always automatically re-thrown at the end of the catch in newer versions of the CLR, so that helps somewhat.

      Turns out that is not true; there are some super-fatal exceptions like that but OOM is not one of them. There was a few years ago a plan for OOM to be one of those but my spies on the CLR team tell me it never happened. I’ll probably do a blog post on this topic at a later date.

  34. 1) If I forget that a database connection might throw an exception if the server is down and the connection can’t be made.

    2) In theory I read the documentation (ha!) but in practice it’s through testing – either automated or manual. I’ve looked into using PEX and code contracts as well. A tool that follows code paths down and tells you “hey, this might throw an XyzException, you know” would be valuable.

    3) Consistency is king, but don’t lock us into being consistent. That is, the language and IDE should guide me towards consistency because that 10th time is probably just an oversight on my part, but I should be able to override that because I know better and I know that the 10th time really is different for some reason.

  35. 1) Yes, mainly related to network communication. Sometimes I forget to check for communication issues on some code path even if I designed the program in such a way that these failures can be safely ignore. I have even added empty catch blocks on several occasions when the very flow of the app was designed in somewhat transactional manner.

    2) Generally no. Sometimes I think of possible exceptions but I do not actively try to find out for every method.

    3) not a lot although now that you point it out I am probably wrong

    I have a couple of questions too.

    1) why do you think there is zero chance of adding this feature to C#. It seems like checked exceptions can be easily added without breaking anything if they are found useful. Now I would say that there is 0 chance that checked exceptions are found useful but you said that there is no point in discussing it so it is not about the usefulness. It seems to me that checked exceptions are a feature very easy to add and even easier to remove. In fact I am willing to bet that Java will remove them by just ignoring them and turning them into a runtime exceptions in the future.

    2) do you happen to know any other languages with checked exceptions besides Java?

    3) I think checked exceptions are very useful as a way of documentation. Is it technically possible that the chain of exceptions is inspected automatically from an assembly and/or source code and presented in the IDE so the developer can see all possible exceptions when calling the method but not being forced to handle them?

    • 1) Read the linked article. Anders didn’t like twelve years ago and it is only more expensive and difficult to add it now.

      2) C++ has a now-deprecated feature called exception specifications.

      3) That would be a good tool, I agree. Does Reflector do that?

      • 3) RedGate have such tool but it gives so many “false positives” that becomes almost useless, tought, I sugest you to try it by yourself.

  36. 1. Yes. Many.

    I wish there were something like catch (Exception) that was not an antipattern. 90 % of my catch statements are. “Something in this operation, usually involving IO or foreign data, didn’t go so well so cancel that whole operation.” I would like to be able to handle anything that could go wrong without handling out of memory, assert, thread abort, and a few other exceptions that should slip through.

    2. I do not have a good technique and so often I get surprises by exceptions.

    It seems to me that a tool that can understand and nagivate code ought to be pretty trivially able to compute the exceptions that might appear at a given point. I would love to be able to hover over something in VS and see all the exceptions it might throw. (You would probably have to filter the list. My guess is that most nontrivial methods can throw NullException, OverflowException and a few others.

    3. Not necesarially. I call a lot of stuff in unit tests without a try/catch. Even if you exclude the unit tests, there are code paths that I care about more than other code paths.

    John Melville

    • The situation you describe is extremely common, but I don’t a “catch everything but XX” would help. Fundamentally, what’s needed is “catch any exception which is thrown in situations where all corruption is confined to objects which will be abandoned”, but that probably isn’t workable; the next best alternative would be to have a clean means of ensuring that any data structure which might get corrupted by an unexpected exception will be expressly invalidated during stack unwinding. While it should be rare for code to “catch” exceptions, it should be common for code to act upon them without any expectation of resolving them (first-pass exception handling should proceed past such handlers when searching for a “catch” block).

  37. 1) Yes. But only in the case where the code being called was designed to use these exceptions to guide the program flow. This is considered a bad practice, but we cant always assume the code we are calling is well written.

    2) I’m all for using general ‘catch (Exception e)’ handlers around suspect code. But only for the case of wrapping it in a new exception and throwing that, in order to add more context for handlers further down the call stack. Sometimes you cant know what exceptions to expect, but something like a NullReferenceException bubbling up from the deep with no context is not helpful.
    As for always handling specific exceptions. I believe you should only consume an exception you can reasonably recover from or take alternative actions. And doing nothing in a catch is never a reasonable action.

    3) If you’re seeing the same code 9 or 10 times it might be time for some refactoring. But you cant really make assumptions about the correct way to handle exceptions. Just because its dealt one way somewhere else in the code doesn’t mean you should blindly copy paste a try catch without understanding why its there. If in doubt, throw it (out).

  38. I have some strong opinions here.

    1) Have your programs had bugs that you fixed by adding exception handling for a specific exception that you did not realize could be thrown?

    Yes, often enough. One recent case that bugs me is a little utility I wrote to test connectivity with a web service I had written. I want to try to connect, and if there was a configuration problem provide an informative message to the user. If there was an application or CLR bug, I wanted to abort with a helpful error log.

    I found it frustrating that there were no broad parent types of exceptions that could let me distinguish between the two, and the documentation was poor. I was reduced to devising as many failure scenarios as I could, and seeing what they threw. My code wound up being ugly, and I have no assurance that it was comprehensive – there are many things that can go wrong with secure web services. This was not just released, but released as sample code for our customers to read.

    2) When you are writing new code that calls methods you didn’t write, how do you know what exceptions you should be handling?

    Some parts of the MSDN documentation are good, some really, really aren’t. Documenting exceptions is usually the first thing to go. Frankly, I often don’t know. Frequently I’m reduced to catch(Exception), which I dislike, although at least I try to rethrow anything I don’t recognise on the assumption that recovery is impossible.

    Are there particular exceptions that you believe should always be handled regardless of what method produces them?

    Yes, application-specific exceptions I wrote myself.

    For example, is it the case that any method that can possibly throw IOException should always be inside a try-catch?

    Somewhere up the call stack there should be something that catches IOException or a parent exception. I don’t feel there should be a general rule that it should be caught immediately.

    3) … For example, if you are writing new code to call a method M, and nine times out of ten elsewhere in your program the call sites for M wraps the call with a try catch that catches FooException, do you see that as a good reason to catch the same exception in the new code?

    If it were not handled somewhere up the call stack, I’d like a tool that would advise me with a warning. I’d like to be able to hide that advice on a case-by-case basis without needing to pollute my code with stuff to feed the tool.

    In general, I feel that it is crucial for good-quality exception handling that the coder can distinguish some broad categories of exceptions, like your four types. The correct approaches to handle each of these types differ wildly, and if you can’t easily distinguish them it’s either painful or practically impossible to do your job properly.

    I think that types are a great way to distinguish them, in fact I think Java’s Throwable, Error, Exception and RuntimeException type hierarchy is a broadly analogous approach to yours and one of the strengths of the Java standard library. I think the .NET library designers really missed an opportunity there and we all pay the price as a result.

    I am regularly frustrated by the lack of thought given to exception type hierarchies, both by the .NET library authors and coders generally. When code fails in unpredictable ways, it frequently doesn’t recover well and frequently gives useless diagnostic information. Maintenance people can waste hours or days as a result.

    And here endeth the rant. I’ll save my rant about checked vs uncheck exceptions for another day. I’m pretty practised at that one.

  39. The exceptions in C# drive me crazy. Too many possible types to catch, but no clearly defined rigid hierarchy. That means every try/catch block is an exercise in frustration because you ever know if you’ve caught the right types until it blows up in production.

    Also, I always wished some really really bad exceptions like “StackOverflow”, “OutOfMemoryException”, “ThreadAbortException”, etc. had a common parent which wasn’t shared with other exception. I should be able to “catch (Exception ex)” and skip the really bad ones (let the app crash), but alas, that’s not meant to be. Unfortunately “SystemException” is too broad and is a child of Exception anyway making it effectively useless.

  40. 1. Yes, absolutely. Often with third party API’s where the documentation is poor, but even with 1st party API’s in some cases like the Windows Phone core API. Some errors I can handle gracefully, other errors happen only intermittently and I can’t reproduce or accurately fix – but can safely ignore without harming the app/data – just a slightly worse UX (such as not loading an image from a web source when I otherwise would have). In any case I am catching specific exception types that I didn’t previously know could be thrown from a method, and handling them. Also, while it’s my own fault, sometimes I don’t even realize I’m calling a method I’m unfamiliar with, and forget to read the docs. Part of that though is most docs either include no exception information, or worse include some that looks complete but really isn’t. I recently had an exception thrown from an MS API for validating xml for use in a security context that threw an exception not listed in the MSDN page for the method.

    2) Generally I have no idea what exceptions I should be handling. IO exceptions are often obvious because of the name/purpose of the method I’m calling, but then I don’t necessarily want to handle all IO exceptions the same way so I still need something more specific. File not found/unauthorized access should perhaps result in a message box, but something that indicates a corrupt file or disk should perhaps kill the app, send a notification or do something more serious. The rest of the time, I only know through reading the docs, guess work or experience.

    There aren’t any exceptions I believe should always be caught, but I believe there are some that should never be thrown (never being 99.99% of the time). i.e you should have a null reference exception thrown in your code. It’s (usually) easy enough to check if something is null, and if it might be you should check that first rather than let the exception be thrown and caught. Almost always a null reference is an accident, and the perf cost of throwing and catching exceptions, possible security issues, not to mention the extra blocks of code over an if/else are uncool as far as I’m concerned. There might be the odd case where, for multi-threading reasons, trying something and letting the null ref get thrown is better than checking (i.e you don’t want to operate on stale reference), but I suspect those would be rare an possibly the sign of bad design anyway. Likewise I generally feel invalid cast/format exception should not be thrown in .Net 2.0+ since we generally have tryparse methods that avoid the exceptions, and that is preferable to me.

    3) In general, not very much. I feel you should only catch exceptions you can handle. If I get a file not found exception at a UI level, then perhaps, depending on context, I can report that to the user or create a new blank file etc. If I get that inside some background process/thread or buried deep in an object model that might be used from a service or back end component then I shouldn’t be showing any UI… at that point it can’t be handled the same way in all places in the code, and in some places probably should go unhandled. I do feel it’s important that every unhandled exception, and often even handled ones, gets logged for diagnostic purposes… so try/catch(log)/throw is a common pattern, but again I don’t want to be logging the same error multiple times if I can help it, so it’s not like I’m putting that in every method.

    What I’d really like to see is something in between checked exceptions and unchecked exceptions. This is perhaps something that could be done in a tool like Resharper (maybe it is ?) or Coverity’s code analysis tools. I want to be able to see when I’m writing a catch block what the possible exceptions are, and have intellisense/autocomplete on the possible/probably exception types. With tooltips or something similar explaining the scenario’s that exception type might be thrown under. I don’t want to have to declare exceptions all the way up like checked exceptions enforce, but I want an accurate, quick and easy way to know what I might want to handle when I’m writing the code. As I’ve said, documentation is often lacking or in complete, and it’s easy to forget to check it. A tool that assists rather than enforces would be great.

    Whether the tool inspects the code being called (my preference as it feels more accurate) or the methods get decorated with the exception metadata, I’m not sure. Perhaps a combination of both.

    Another thing that bugs me (thought not directly related to un/checked exceptions) but I don’t know how to solve is code that throws the same exception type for multiple reasons, with only the error message text for the caller distinguish the reason by. I’ve seen plenty of API’s that throw InvalidOperationException from a method for different reasons, with no way for a catch clause to determine the specific cause of the exception. Checking the text is bad for obvious reasons (dynamic messages, localization, messages changes over time etc).

    I think LINQ’s Single() extension method is a cuplrit – it throws InvalidOperationException for both no items in the collection and more than one item – sometimes it would be useful to know which was the case. It is certainly useful to know which when you didn’t expect either condition and you logged the error. Great – now my log tells me that I had the wrong number of items, but I didn’t expect that to happen so I don’t know why it did, and now I can’t even tell if I’m looking for a situation where I had too many or too few items. This is hardly the worst example either, as at least the two conditions are similar if not exactly the same. Plenty of other API’s I’ve encountered throw the same exception type for completely different and unrelated reasons.

    Perhaps a code analysis rule that says don’t throw the same exception type from multiple locations in a method if a default constructor, or constructor with only the error message provided, is used ?

    • For Single(), I’d suggest that if it matters whether there were no elements or multiple elements, the code would be clearer if one checked explicitly. It’s more verbose of course, but it signals more clearly to anyone reading the code that it matters. The catches may not be on the screen at the time.

      On a related note, I love Java’s IsEmpty() method on collections.

  41. Joshua and bmurphy make some excellent points in my opinion, and I agree that lack of common parents, or too broad usage of a common parent is a problem often when handling exceptions in C#.

  42. The answers to these questions depend heavily on context.

    Handling things like IOException are unavoidable in certain scenarios – e.g. when you need to take an alternate action when a file does not exist, you can’t rely on !File.Exists because that races with an attempt to open the file.

    Some operations need to make and track progress in a defined way, e.g. for idempotent restart where the world can’t fit in a transaction. Here the nature of failure is important as it guides possible cleanup and potential resume location.

    Different classes of applications vary in their need for exception handling. Almost all server-class apps shouldn’t care about catching exceptions 99.9% of the time – they should just bubble up to the original request dispatch, log, and return an error.

    Ideally the situation would be the same in most GUI apps, if the exceptions have human-readable messages and can be displayed in an intelligible fashion – e.g. a validation error popping up beside a data-bound control having bubbled up from a complex domain model. But there’s much more need for filtering in this scenario, as many exceptions can be classed as bugs rather than something the user can be expected to deal with. Whether to fail fast and lose all the user’s data, or struggle on in a semi-unknown state, or try and save recovery info and restart – opinions differ and depend on the application domain.

    When trying to filter exceptions, gotchas are common wrappers like TargetInvocationException. Unwrapping all these guys can be tricky, as any code path that flows through a third party may end up wrapping exceptions that bubble back out in some custom wrapper.

    Most people misuse exceptions, IMO, and try far too often to catch them. Java especially encourages pollution of the namespace with redundant wrapper exceptions at module boundaries, and some people copy this practice elsewhere. The combination of Java and C++ really messed up the common programmer understanding of exceptions, to the point that new languages like Go and Rust don’t have them (though technically Rust has several features that can be viewed as intersections of exceptions).

    The biggest thing that puzzles people with exceptions is the fact that the set of throwable exceptions for any given routine is a function of how the routine is implemented – exceptions intrinsically break abstraction. A common Java approach of catching exceptions and rethrowing them wrapped up at module boundaries is a complete waste of time, because you can’t do anything meaningful with a wrapped exception if you don’t know what caused it, which requires unwrapping it again.

    tl;dr: catching exceptions may be necessary very near the site of the error (especially common with races / non-determinism / concurrency (e.g. a network stream)), may need careful transaction handling somewhere in the middle of the stack, but almost always should end up at the outermost request / response handler or event loop, where they should log / dialog box / force-quit depending.

    • “A common Java approach of catching exceptions and rethrowing them wrapped up at module boundaries is a complete waste of time…”

      I disagree. How is it easier to interpret library exceptions when you’re having to catch the low-level exceptions thrown by the internals of code you’re depending on? What does that OverflowException from four levels further down in the stack mean for the future of your process? What if the implementation changes and a new exception type can bubble out?

      A better way (though still hardly ideal, I admit) is for the library to continue to wrap exceptions – but to use its own exception hierarchy to distinguish different failure modes.

      • Does Java not include stack traces with exceptions? I’ve quite literally never not known exactly what library threw an exception. Unless you’re suggesting that your code should be catching these wrapped exceptions and applying different logic based off of which library they originated from. That is quite unrealistic in my experience.

        • It does, but if the library code is not available interpreting the stack trace is difficult. Specifically, if the body of code beneath your call is large enough, a specific exception might be thrown by multiple places under multiple circumstances, and neither the type nor the stack trace give you enough to go on to identify what exactly went wrong and what you should do about it.

    • I disagree with your criticism of Java exception patterns. When writing exceptions, I think the key motivators are that:

      (i) The low-level exceptions at the bottom of the stack are vital because they’re the ones that tell a maintenance person what exactly went wrong, and how to fix it. It is vital that these are logged with all the detail possible, including the stack trace.
      (ii) This will obviously be unintelligible to most users. Users need a clear explanation of what the failure means in terms of the task they desire the software to perform, in their local language.

      My ideal pattern is therefore for each module in the software stack to catch lower exceptions (except what Eric calls fatal exceptions, where the execution environment is busted and the app should just abort) and wrap them in a custom exception that makes sense in terms of that module’s API. The UI exception class can worry about i18n in feedback on the screen, but the whole lot is logged for the maintainer. That way, abstraction is preserved, only the maintainer reading the log needs to unwrap it. Each API only throws some small number of exceptions that make sense to callers of the API, which makes them easier to document. Most important of all, the user sees something useful to them and the maintainer sees the full story, from the initial cause through to what the consequences were.

      For example, in a word processor, the guts of the document persistence code may throw an IOException, which would be caught and wrapped in a DocPersistenceException when it passes out of the document class. The UI layer could catch this and wrap it in a UserException class with an i18ned message informing the user that their doc didn’t save properly. This would be logged and feed the UI notification.

      If this pattern was followed more consistently it would have saved me personally heaps of time on bug hunts, and plenty of frustration.

      The caller of an API IME usually doesn’t care about the cause of an exception, the key thing is that the API didn’t work. On the occasions where it does matter, yeah, unwrapping the exception does break the abstraction. Either a new API-level exception could be written to allow callers to distinguish, or the API could just be a leaky abstraction, depending on which keeps the software as a whole the clearest.

  43. 1) Yes, though rarely. This kind of “fix” generally indicates either a real bug in a closed third-party API for which no other workaround exists, a bug that you’ve referred to as “vexing” and therefore lacking any alternative API of the Try* variety, or generally just an unavoidable exception that you’ve referred to as “exogenous”, typically due to concurrency in an external system.

    2) I don’t know which exceptions I should be handling until they prove to be exceptional circumstances, at which time I actually review them and determine whether I need to fix a bug or use an alternative API. I simply never waste time attempting to handle exceptions for contingency. It’s too easy to get into trouble without fully considering the implications of all possible exceptions, and I certainly don’t want to make debugging more difficult for myself in the future. There are absolutely no types of exceptions that should be handled blindly; e.g., catching IOException implicitly catches DirectoryNotFoundException and a few others, which have vastly different meanings.

    3) None. I consider an API’s public contracts at each individual call site, and that includes exception handling, even though technically in C# we must rely on experimentation and sometimes documentation to determine the types of exceptions that may be thrown and in which circumstances. In other words, it’s always important to consider the state of the environment at the time of the call and the arguments supplied, if any, which can easily differ between call sites. And anyway, when I find that a third-party API requires me to use the same exception-handling pattern every time that I call it, which could mean that it’s a poor design to begin with, then I can apply the DRY principal to reduce the number of call sites to 1 so that I don’t have to remember how to properly call the API each time that I need it.

  44. The only times when I care about what kind of exception a method may throw are those when I need to deal with a MutexAbandonedException, or SecurityException, or some other exception that really is not an exception at all… all right, I’ll stop here: don’t feel like going into a lengthy (and, likely, heated) debate about what an exception is and what the word ‘exception’ means. Basically, if all I need is to ensure that in the unlikely event of an emergency my program degrades gracefully instead of crashing and burning with an ugly and scary system error message meaningless to the vast majority of users, I just go, ‘catch (Exception ex)…’ if, however, an exception happens as a part of normal functioning of the program (please, no debate about whether or not an exception can be normal, not now πŸ™‚ ), then, and only then I would care about what kind of exception it is. Which means, to me, checked exceptions would be redundant and rather annoying.
    Thank you for your attention. πŸ™‚

  45. 1) Have your programs had bugs that you fixed by adding exception handling …

    Occasionally, most prominently the already mentioned UnauthorizedAccessException or InvalidOperationException from methods like Process.Kill (to “handle” worker processes).

    “Fixed” in a related way could also include adding Cancel options to the application and then catching OperationCanceledException.

    2) When you are writing new code that calls methods you didn’t write, how do you know what exceptions you should be handling?

    Trial and error, mostly. Sometimes the documentation is sufficient, but the exception type is not and may not include good enough indication whether the issue is a warning (missing/prohibitive/impractical user input validation or a transient issue like SQL deadlock) or an unrecoverable error (the already mentioned hard to discern EEE, TAE, SOE). It is always hard to know how the underlying component handled the exception and whether it is still usable or not. (e.g. SQL connection still open?). Then we might have a look with Reflector or similar tools. For instance, we may have OOM due to VM fragmentation and there may be ways to react, other than FailFast.
    Then again, the component might have a plug-in architecture itself, so it is outright impossible to do the right thing.
    Win32Exception is a case we look up in the documentation. For the underlying API we identified, again, with Reflector.

    3) How much weight do you give to consistency of exception handling?

    That depends on the level of the try-ed operation. If it is high up in the throwing component, very much, like ReportViewer’s LocalProcessingException.

    Otherwise, more or less only on something I would call “entry”, that is when we start using caller supplied objects. Then we might handle XmlException or the like, but not later on, when we handle semi-processed objects.

  46. 1. Yes

    2. I usually preferred to catch exception at bottom of call stack (first/initial method), to log the exception and handle output (mostly common for all exception) sent back to request.

    3. However i would catch specific exception in specific method (or in method calling), if based on that specific exception, output/result needs to be manipulated.

  47. Pingback: Dew Drop – March 5, 2014 (#1735) | Morning Dew

  48. 1) I’ve found, that when using the DataContractJsonSerializer sometimes it may throw ArgumentNullException even when the stream provided to ReadObject(Stream) is not null, when perhaps you’d expect it to throw the (handled) SerializationException; at least on the Windows Phone implementation. I’ve also had the inverse – with Linq to SQL on Windows Phone, the exceptions that can be thrown are of a type that is not legal to add a reference to – this leaves you in the sticky situation that you can only handle SqlCeException by catching all exceptions, and inspecting (per http://channel9.msdn.com/events/MIX/MIX11/DVC12 ) – this can lead to bugs by forgetting to handle other exceptions like out of memory, etc. appropriately.

    2) This is where good documentation comes in handy – and I tend to take the opinion that a method should declare which exceptions it throws (but not necessarily the things it calls), and a programmer friendly description as the cause – if that cause can be handled, and worked around, then awesome, I’ll catch/handle it. For example, if I’m loading data from a remote webserver, (i.e. calling down to methods on WebRequest and/or DataContractJsonSerializer), then I may handle the different possible exceptions early, rather than delegating to the child – so I might catch WebException, ArgumentNullException and SerializationException and rethrow as a “no data available” exception with the InnerException set, or return null instead of an empty set if the caller only cares for success/failure, etc.

    3) I’d only catch/handle the exception if I can handle it safely (even if “handle” means log and continue), this implies that the only consistency is at the UI level, rather than based on what I’m calling.

  49. 1) Yes — typically in cases where code I’m calling that declares that all its expected exceptions subclass a specific exception type, and it misses a catch and re-raise case. One instance sticks in my mind where the type name of the exception type being re-raised matched the name of a PowerShell exception type and R# helpfully offered the latter namespace as an option — and the unexpected “using System.Management.Automation” directive for a file in that particular code layer didn’t get spotted at code review.

    2) I trust MSDN at the library level (fixing up as required when deficiencies are observed in test) and read the code for internal dependencies. Everything else gets firewalled by the catch and re-raise idiom in an adapter layer (with the translation being refined while testing).

    3) Tactical exception handling depends on the circumstances in which the issue may arise. Strategic exception handling e.g. guarding WCF service threads, or providing consistent reporting for database issues, that gets done with code generation layers at the respective interfaces to guarantee consistency.

Leave a comment