Friday, 5 February 2016

Why TypeInitializationException has Null inner Exception?

This TypeInitializationException occurs when a Type is failed to load because during Type initialization. Normally, When this exception occurs the InnerException property contains the actual exception details about why the initialization failed. But sometime it happens to be Null and so we have Questions about the same.

Let’s take an example –

 class Program

    {

    static Program()

    {

        var initialBootDrive = Directory.Exists("C:\\logs\\BootLogs");

        if(!initialBootDrive)

        {

            throw new IOException("Directory does not exist");

        }

    }

 

    static void Main(string[] args)

    {

      Console.WriteLine("Press any key");
      Console.ReadLine();

    }

    }

This will cause the exception to occur. Because the static constructors can not be called explicitly but will execute when the Type will be first accessed. In this case the Type will be accessed for initialization.

The above case is special case which I want to discuss in this post. The TypeInitialization will occur with null InnnerException.



There is no “View Detais” options. Moreover if click “Copy exception detail to the clipboard”.

You’ll get this –

System.TypeInitializationException was unhandled Message: An unhandled exception of type 'System.TypeInitializationException' occurred in mscorlib.dll Additional information: The type initializer for 'TypeInitializationExceptionTest.Program' threw an exception.

Not much details. Right? There’s no Inner Exception so you’ll never know what causes this exception to occur.

The reason, is that TypeInitializer of Entry method(Main) class is failed. Since no type was initialized at this very moment, so the TypeInitializer has no type information to report about the failed type in TypeInitializationException.

As explained more by Jon Skeet,Once a type initializer has failed once, it is never retried. The type is dead for the lifetime of the AppDomain. (Note that this is true for all type initializers, not just for types with static constructors. A type with static variables with initializer expressions, but no static constructors, can exhibit subtle differences in the timing of the type initializer execution - but it'll still only happen once.

But if you remove the static constructor from the Entry Type (i.e. Program) to other class and then refer that class in Entry method. you'll get the InnerException on TypeInitialization exception.

static class BootStrapper
{
    public static bool Initializing;
 
    static BootStrapper()
    {
        var initialBootDrive = Directory.Exists("C:\\logs\\BootLogs");
        if (!initialBootDrive)
        {
            throw new IOException("Directory does not exist");
        }
    }
}
 
    class Program
    {
    static void Main(string[] args)
    {
        // The first access to the class will cause the static constructor to execute.
        BootStrapper.Initializing = true;
 
        Console.WriteLine("Press any key");
        Console.ReadLine();
    }
    }

Now if you run it you’ll get the expected behavior.

Final Remark – Keep the Entry (Main) class as clean as possible from Static member or constructor initialization that throws exception.
If necessary either avoid throwing exception, or only throw exception when those member are being accessed in during execution of application.