Framework Design Guidelines: The right number of exceptions

A reader asks me about a salutation where they are catching a SoapException and wrapping it with their own API specific exception type.  I think this is a fairly common scenario so I wanted to start a dialog about it here.


Part of this is covered in chapter 7 of Framework Design Guidelines.


First, it is goodness to wrap the SoapException with your own custom exception type.  Essentially you are abstracting away some implementation detail of your framework.  Today you may use ASMX, tomorrow you may use Indigo.. I mean WCF… to access it, you don’t want the public contract of your framework to change as those implementation details change.


In this particular case the SoapException could indicate 100+ reasons why the call failed, is it a good idea to wrap all 100+ reasons into one exception or should we create 100+ exceptions to expose that level of detail to the API caller?  Neither of these is a good idea.  Using just one exception is likely to mask issues together that should be called out and creating over 100 exception types is way overkill.   So forget the implementation detail of how the errors get to you (the SoapException) and think only about how consumers of your framework are going to want to consume those errors.  For example there are probably some logical groupings of errors that the user will want to handle in a very similar way.  For example any kind of error on the server side may want to be logged for an admin to look at.  Group each of these in their own exception type (maybe subclass of common base) possibly with some programmatic way to find the specific issue if needed.  You should also think if there are errors you can handle in your own framework, for example your framework might decide to retry twice on a “server busy” error before it throws it back to the caller.  All such cases should be well documented of course. 



Have other folks run into this scenario?  What did you do?


Comments (14)

  1. I had to deal with this issue with our API. It uses WSE Web services behind it. The user of our library may have to contend with the complexity of both SoapExceptions and WebExceptions. I wrapped both of these as inner exceptions into our own custom ConnectionException. I then assigned codes to the most common exception conditions that our users will likely come across (e.g., NameResolutionFailure and ProtocolError).

    In addition, the user can turn off this ConnectionException behavior and catch the raw exceptions.

    I feel like this is a good compromise because it makes the default behavior easy without hiding away any of the raw exception details.

  2. Sean Chase says:

    For external ASMX, I prefer logging exceptions and throwing a custom exception that contains a support tracking number. Of course, I don’t wrap certain things such as WSE functions that throw SOAP exceptions as they should, or XSD schema validation failures (I want the user to see those)….



    [return : XmlElement("ResponseBasedOnXsd")]

    public ResponseBasedOnXsd GetSomeKindOfInfo([XmlElement("RequestBasedOnXsd")] RequestBasedOnXsd request)


    base.ValidateRequestAgainstSchema(request, "RequestBasedOnXsd.xsd");

    //WSE GetUsernameToken



    //Do stuff

    return response;


    catch (Exception e)


    throw base.GetCustomException(e);




    protected CustomException GetCustomException(Exception e)


    //Create a CustomException so it gets published to the exception log

    CustomException wrapperException = new CustomException(e.Message, e);

    //Publish the exception internally for support


    //throw a new exception that does not contain any internal application-specific data to the user

    return new CustomException(String.Format("An internal error occured. Support issue tracking number {0} has been assigned.", wrapperException.SupportTrackingNumber));


  3. Michael Vanhoutte says:

    I completely agree with the idea behind your guideline and I have been trying to follow it myself for some time now.

    However, I found it very difficult to implement because it very much relies on whether or not the API developer has properly documented all the exceptions that his API can throw. Since this often isn’t even the case in the .NET framework itself…

  4. Matthew says:

    >> Group each of these in their own exception type (maybe subclass of common base) possibly with some programmatic way to find the specific issue if needed.

    Why not just have 100 exception classes rather than (for example) 8 of them, each of them with an enum of 12 possible ‘underlying’ exceptions?

    I have never understood the argument against writing exceptions? They are very fast to write (cut and paste and edit in less than a minute). As soon as you have one exception meaning more than one thing, you subvert the whole try .. catch ex as WhatEverException mechanism.

    Of course, with 100 exceptions you would have an inheritance hierarchy (ie the 8 ‘exceptions’ would be there as MustInherit) – so if someone wanted to catch a ‘grouping’ of exceptions they still could…

  5. Chris says:

    Be careful about auto-retry. If you auto-retry twice and the layer above your code and the layer above that code all do, you just tried 8 times when only once was probably needed.

  6. I had posted on supporting multiple retries support in C#. See

    Raymond Chen picked up this entry and pointed out that this is not a good idea at all in

    I feel that a blanket statement does not hold in this case. Case-by-case basis you might be forced to use this retry-logic where you need to try couple of times before giving up. See for my reponse to Raymond Chen

  7. Our policy is never to catch exception that you don’t know how to handle, just leave the upper layer to handle them. The pattern of catching and throwing a general framework exception will eventually cause the “General Error” message box or log line that all of us are known very well. I think it’s a bit naïve to think that you can switch from SOAP to WCF in your framework without any breaking changes.

    Personally I think the Microsoft should have given us a generic CommunicationException that in is InnerException would hold the implementation error details, You (MS) did it for XML and it works (at least for us) pretty good.

  8. Bart Elia says:

    We built our own facade / proxy abstraction for web services and client proxies 4 years ago before we heard about indigo. In it, we catch all exceptions in the facade on the server and serialize the exception into the inner exception of the soapexception. On the client, we deserialize the exception and ‘re-throw’ the inner exception.

    While not for high speed scenarios, the calls are usually at times where a form is being saved so not bad to have an extra few milliseconds for the nicer client side exception handling logic.

  9. Ben says:

    Hey Brad, I think auto-correct bit you in that first sentence. Did you mean "situation" not "salutation"?

    Great advice btw on the grouping. I like to group things as they naturally fall. I had to deal with a legacy system that returned error codes, which we mapped onto a variety of exceptions.

  10. ericgu says:

    I used to be a big advocate of wrapping, but now I’m not so sure. You may end up having to write:





    catch (LibException e)


    if (e.InnerException.GetType() == typeof(HiddenApiException))


    // do some recovery



    and end up making the mistake I did. Not to mention the fact that the user may write recovery code for a LibException that they’ve seen and not realize it could be caused in many other cases.

    I put 250,000 rows in a database recently because of some messed-up recovery code…

  11. Matthew says:


    Why not just have LibException inherit from HiddenApiException?

  12. Klaus Enevoldsen says:

    On a project that I am working on, we have implemented a class named ServerException that contains information about which exception occured on the server.

    The Web Services does not throw exceptions, but instead wraps the exception in Xml and sends the Xml to the client. The client then checks the return object and throws a ServerException which has properties that returns details about the exception and handle them acordingly.

  13. Rusty Zarse says:

    It makes perfect sense to catch a soap exception and then throw a more useful, custom exception up the stack. I thought I’d point out however, that you should NEVER wrap an exception in a MORE generic exception then the exception you catch. For example, never catch a database exception and then throw the same exception as a generic ApplicationException. If you have value to add, more information, or a more specific exception, then it is a good approach. However, if all you do is catch and re-throw as ApplicationException, what is the value? In fact, it has negative ramifications: the developer consuming the method will receive an exception that may bypass his structured handler. He may have placed an OracleException catch block in his code that never fires because the exception was wrapped in something more generic. So, if you’re going to wrap, wrap in a more specialize or specific exception and never as a more generic exception.