DEV Community

Niels Swimburger.NET πŸ”
Niels Swimburger.NET πŸ”

Posted on • Originally published at swimburger.net on

Rethrowing your exceptions wrong in .NET could erase your stacktrace

You may be erasing your stacktrace if you are catching and rethrowing exceptions the wrong way. This could make debugging a nightmare because you don't know where the exception was originally thrown.

You are erasing parts of the stacktrace if you are catching and rethrowing exceptions like this:

try
{
    DoWork();
}
catch (Exception ex)
{
    throw ex;
}

Enter fullscreen mode Exit fullscreen mode

If you catch the rethrown exception and print out the stacktrace, you will notice that there's no mention of the DoWork method where the exception was originally thrown.

System.Exception: Exception of type 'System.Exception' was thrown.
    at CatchRethrow.Program.IncorrectCatchAndReThrow() in /home/azureuser/CatchRethrow/Program.cs:line 50
    at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 22
Enter fullscreen mode Exit fullscreen mode

That's because it was overwritten when the exception was rethrown.

The correct syntax is to use throw; instead of throw ex;:

try
{
    DoWork();
}
catch (Exception ex)
{
    throw;
}
Enter fullscreen mode Exit fullscreen mode

If you catch the rethrown exception now and print out the stacktrace, the DoWork method is printed as part of the stacktrace:

System.Exception: Exception of type 'System.Exception' was thrown.
    at CatchRethrow.Program.DoWork() in /home/azureuser/CatchRethrow/Program.cs:line 56
    at CatchRethrow.Program.CorrectCatchAndThrow() in /home/azureuser/CatchRethrow/Program.cs:line 34
    at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 12
Enter fullscreen mode Exit fullscreen mode

Luckily, there's a code analysis rule "CA2200: Rethrow to preserve stack details" that will warn you about this.

Here's the full sample of the code used to demonstrate the issue above:

using System;

class Program
{
    static void Main(string[] args)
    {
        // correct catch/throw
        try
        {
            CorrectCatchAndThrow();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            /*
            System.Exception: Exception of type 'System.Exception' was thrown.
                at CatchRethrow.Program.DoWork() in /home/azureuser/CatchRethrow/Program.cs:line 56
                at CatchRethrow.Program.CorrectCatchAndThrow() in /home/azureuser/CatchRethrow/Program.cs:line 34
                at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 12
            */
        }

        // incorrect catch/throw
        try
        {
            IncorrectCatchAndReThrow();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            /*
            System.Exception: Exception of type 'System.Exception' was thrown.
                at CatchRethrow.Program.IncorrectCatchAndReThrow() in /home/azureuser/CatchRethrow/Program.cs:line 50
                at CatchRethrow.Program.Main(String[] args) in /home/azureuser/CatchRethrow/Program.cs:line 22
            */
        }
    }

    static void CorrectCatchAndThrow()
    {
        try
        {
            DoWork();
        }
        catch (Exception ex)
        {
            throw;
        }
    }

    static void IncorrectCatchAndReThrow()
    {
        try
        {
            DoWork();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    static void DoWork()
    {
        throw new Exception();
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)