What really went wrong ? Check the inner exception

In his recent overview on Exceptions Karl briefly mentioned the inner exception. By passing an exception to the constructor of the new exception, the exception passed in becomes the new exception’s InnerException property.

private void workWithFile()
{
    try
    {
        // do something        
    }
    catch (FileNotFoundException ex)
    {
        throw new Exception("Cannot find the file", ex);
    }
}

Code using this method can catch the exception

try
{
    workWithFile();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Now this exception caught here does not contain very much useful information. It would be interesting to know the name and location of the missing file. To get at that you have to inspect the inner exception.

try
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    FileNotFoundException fnfEx = ex.InnerException as FileNotFoundException;
    if (fnfEx != null)
        Console.WriteLine(fnfEx.FileName);
}

Instead of discussing the design issues here (drop the catch in the method and just catch a  FileNotFoundException in the consuming code) I want to take a look on a situation in real life where the inner exception does tell the story.

When initializing a sessionfactory in nHibernate a lot of things can go wrong and will throw an exception. My nHibernatemanger does not handle any of them, so my code will have to check. At first sight this might look OK

try
private void reportException(Exception ex)
{
    Console.Write("* ");
    Console.WriteLine(ex.GetType().ToString());
    Console.WriteLine(ex.Message);
    Console.WriteLine();
}

[Test]
public void CanReportOuterException()
{
    try
    {
        INhibernateHelper nhh = GetNHhelper();
    }
    catch (Exception ex)
    {
        reportException(ex);    
    }
}

Running the code will not make me much wiser

Also here the real information is in an inner exception. As each (inner) exception can have another innerexception my code is going to handle every inner exception it can find

[Test]
public void CanReportAllExceptions()
{
    try
    {
        INhibernateHelper nhh = GetNHhelper();
    }
    catch (Exception ex)
    {
        while (ex != null)
        {
            reportException(ex);
            ex = ex.InnerException;
        }
    }
}

A stack of three exceptions turn up. Together they describe very well what really went wrong. In this case I misspelled the name of the mapping assembly.

I have "misused" resharpers unit test runner to develop this code. In fact the result is much like the testrunner’s report on handling an exception not caught by a test.

[Test]
public void CanCreateHelper()
{
    INhibernateHelper nhh = GetNHhelper();
    Assert.IsNotNull(nhh);
}

Note that the runner lists the exception the other way round, starting at the most inner exception.

Instead of delving though the stack of exceptions you could use the ToString() method of the exception. Which results in a bulky string including information on the inner exceptions and more. But this info is not as well structured and misses the type info of the inner exceptions.

I’m not quite sure why nHibernate does wrap its exceptions this way, but what I have learned is to look inside.

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