Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

Getting the innermost .NET Exception


:P
On this page:

Here's a trivial but quite useful function that I frequently need in dynamic execution of code: Finding the innermost exception when an exception occurs, because for many operations (for example Reflection invocations or Web Service calls) the top level errors returned can be rather generic.

A good example - common with errors in Reflection making a method invocation - is this generic error:

Exception has been thrown by the target of an invocation

In the debugger it looks like this:

VsException

In this case this is an AJAX callback, which dynamically executes a method (ExecuteMethod code) which in turn calls into an Amazon Web Service using the old Amazon WSE101 Web service extensions for .NET. An error occurs in the Web Service call and the innermost exception holds the useful error information which in this case points at an invalid web.config key value related to the System.Net connection APIs.

The "Exception has been thrown by the target of an invocation" error is the Reflection APIs generic error message that gets fired when you execute a method dynamically and that method fails internally. The messages basically says: "Your code blew up in my face when I tried to run it!". Which of course is not very useful to tell you what actually happened. If you drill down the InnerExceptions eventually you'll get a more detailed exception that points at the original error and code that caused the exception. In the code above the actually useful exception is two innerExceptions down.

In most (but not all) cases when inner exceptions are returned, it's the innermost exception that has the information that is really useful.

It's of course a fairly trivial task to do this in code, but I do it so frequently that I use a small helper method for this:

/// <summary>
/// Returns the innermost Exception for an object
/// </summary>
/// <param name="ex"></param>
/// <returns></returns>
public static Exception GetInnerMostException(Exception ex)
{
    Exception currentEx = ex;
    while (currentEx.InnerException != null)
    {
        currentEx = currentEx.InnerException;
    }

    return currentEx;
}

Update:
As it turns out .NET already provides for this functionality via Exception.GetBaseException() (see comments). Ah EGG ON MY FACE, but only shows that it's so easy to miss useful functionality in the base framework when it is so rich :-)

This code just loops through all the inner exceptions (if any) and assigns them to a temporary variable until there are no more inner exceptions. The end result is that you get the innermost exception returned from the original exception.

It's easy to use this code then in a try/catch handler like this (from the example above) to retrieve the more important innermost exception:

object result = null;
string stringResult = null;
try
{
    if (parameterList != null)
        // use the supplied parameter list
        result = helper.ExecuteMethod(methodToCall,target, parameterList.ToArray(),
                            CallbackMethodParameterType.Json,ref attr);
    else
        // grab the info out of QueryString Values or POST buffer during parameter parsing 
        // for optimization
        result = helper.ExecuteMethod(methodToCall, target, null, 
                                      CallbackMethodParameterType.Json, ref attr);
}
catch (Exception ex)
{
   Exception activeException = DebugUtils.GetInnerMostException(ex);
    WriteErrorResponse(activeException.Message,
                      ( HttpContext.Current.IsDebuggingEnabled ? ex.StackTrace : null ) );
    return;
}

Another function that is useful to me from time to time is one that returns all inner exceptions and the original exception as an array:

/// <summary>
/// Returns an array of the entire exception list in reverse order
/// (innermost to outermost exception)
/// </summary>
/// <param name="ex">The original exception to work off</param>
/// <returns>Array of Exceptions from innermost to outermost</returns>
public static Exception[] GetInnerExceptions(Exception ex)
{
    List<Exception> exceptions = new List<Exception>();
    exceptions.Add(ex);
    
    Exception currentEx = ex;
    while (currentEx.InnerException != null)
    {
        exceptions.Add(currentEx);
    }

    // Reverse the order to the innermost is first
    exceptions.Reverse();

    return exceptions.ToArray();
}

This function loops through all the InnerExceptions and returns them and then reverses the order of the array returning the innermost exception first. This can be useful in certain error scenarios where exceptions stack and you need to display information from more than one of the exceptions in order to create a useful error message. This is rare but certain database exceptions bury their exception info in mutliple inner exceptions and it's easier to parse through them in an array then to manually walk the exception stack. It's also useful if you need to log errors and want to see the all of the error detail from all exceptions.

None of this is rocket science, but it's useful to have some helpers that make retrieval of the critical exception info trivial.

Resources

DebugUtils.cs utility class in the West Wind Web Toolkit

Posted in CSharp  .NET  

The Voices of Reason


 

James
July 01, 2011

# re: Getting the innermost .NET Exception

Hi Rick, I think your 'GetInnerMostException' exception might be redundant as there is actually an Exception.GetBaseException() method which does the same thing. I made the same mistake of rolling my own before I found it.

John Hoven
July 01, 2011

# re: Getting the innermost .NET Exception

You can also use Exception.GetBaseException to replace your first little loop where all you need is the, well, base exception.

http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception.aspx

Cheers,

John

Alex Reitbort
July 01, 2011

# re: Getting the innermost .NET Exception

Why not use Exception.GetBaseException instead of GetInnerMostException?

Dominic Zukiewicz
July 01, 2011

# re: Getting the innermost .NET Exception

Hi Rick,

Theres also :

try
{
//...
}
catch(Exception e)
{
     Exception realException = e.GetBaseException(); // Since .NET 1.0 I believe
}

Nathan Baulch
July 01, 2011

# re: Getting the innermost .NET Exception

What about using the existing GetBaseException method on the Exception class?

Rick Strahl
July 01, 2011

# re: Getting the innermost .NET Exception

Ah yes, the wonders of not RTFM. Thanks all, only showing my ignorance occasionally. Nothing to see here. :-)

Omer Raviv
July 01, 2011

# re: Getting the innermost .NET Exception

As an aside, I find it quite useful to define a Generate method
        /// <summary>
        /// Returns a sequence of values consecutively generated by a generator function.
        /// </summary>
        public static IEnumerable<T> Generate<T>(T initial, Func<T, T> generator)
        {
            T current = initial;
            while (current != null)
            {
                yield return current;
                current = generator(current);
            }
        }


This is useful in many different situations: getting all the parents of a tree node, etc. In this case it can be used as
 Exception innermostException = EnumerableEx.Generate(exception, e => e.InnerException).Last(); 

Jonathan Dickinson
July 01, 2011

# re: Getting the innermost .NET Exception

While the exception code is not nessecary, you have demonstrated something else important. Nobody else noticed the lack of recursion? Very nice code. Too many devs use recursion these days, without thinking what consequences a StackOverflowException will have (kills your process, no questions asked).

hatchan
July 04, 2011

# re: Getting the innermost .NET Exception

Another nice way to get all inner exceptions:
/// <summary>
/// Returns all inner exceptions of the given exception.
/// </summary>
public static IEnumerable<Exception> InnerExceptions(this Exception exception)
{
    while (exception.InnerException != null)
    {
        yield return exception.InnerException;
        exception = exception.InnerException;
    }
    yield break;
}

You can then use linq to get certain exceptions using linq operators like Where() or OfType()

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024