How can I get the line number which threw exception?

Viewed 262571

In a catch block, how can I get the line number which threw an exception?

14 Answers

I added an extension to Exception which returns the line, column, method, filename and message:

public static class Extensions
{
    public static string ExceptionInfo(this Exception exception)
    {

        StackFrame stackFrame = (new StackTrace(exception, true)).GetFrame(0);
        return string.Format("At line {0} column {1} in {2}: {3} {4}{3}{5}  ",
           stackFrame.GetFileLineNumber(), stackFrame.GetFileColumnNumber(),
           stackFrame.GetMethod(), Environment.NewLine, stackFrame.GetFileName(),
           exception.Message);

    }
}

I tried using the solution By @davy-c but had an Exception "System.FormatException: 'Input string was not in a correct format.'", this was due to there still being text past the line number, I modified the code he posted and came up with:

int line = Convert.ToInt32(objErr.ToString().Substring(objErr.ToString().IndexOf("line")).Substring(0, objErr.ToString().Substring(objErr.ToString().IndexOf("line")).ToString().IndexOf("\r\n")).Replace("line ", ""));

This works for me in VS2017 C#.

Convert.ToInt32(ex.StackTrace.Substring(ex.StackTrace.LastIndexOf(' ')));  

This will give the Exception line no.

Extension Method

static class ExceptionHelpers
{
    public static int LineNumber(this Exception ex)
    {
        int n;
        int i = ex.StackTrace.LastIndexOf(" ");
        if (i > -1)
        {
            string s = ex.StackTrace.Substring(i + 1);
            if (int.TryParse(s, out n))
                return n;
        }
        return -1;
    }
}

Usage

try
{
    throw new Exception("A new error happened");
}
catch (Exception ex)
{
    //If error in exception LineNumber() will be -1
    System.Diagnostics.Debug.WriteLine("[" + ex.LineNumber() + "] " + ex.Message);
}

Line numbers will be included in the stack trace if the library which generated the exception is compiled with debug symbols. This can be a separate file (*.pdb) or embedded in the library.

For .NET Core, .NET 5 and later, to have full exception line numbers in release builds, configure the project as follows:

<PropertyGroup>    
  <DebugSymbols>true</DebugSymbols>
  <DebugType>embedded</DebugType>

    <!-- Only enable the following if the line numbers mismatch -->
    <!--<Optimize>false</Optimize>-->
    
    <!--
      Additional properties which may impact how printed line numbers match the source code line numbers are listed here:
      https://docs.microsoft.com/en-us/dotnet/core/run-time-config/compilation
    -->
</PropertyGroup>

The above configuration will include debug symbols directly with the built files, which can be published as nugets.

An alternative to the above is to restore debug packages together with the main nuget packages, which is currently not yet supported: https://github.com/NuGet/Home/issues/9667

Now get the exception line numbers:

try
{
    throw new Exception();
}
catch (Exception ex)
{
    // Get stack trace for the exception with source file information
    var st = new StackTrace(ex, true);
    // Get the top stack frame
    var frame = st.GetFrame(0);
    // Get the line number from the stack frame
    var line = frame.GetFileLineNumber();
}

If your stack trace is bigger than one it should be:

var st = new StackTrace(es, true);
// Get the top stack frame
var frame = st.GetFrame(st.FrameCount - 1);

// Get the line number from the stack frame var line = frame.GetFileLineNumber();

Working for me:

var st = new StackTrace(e, true);

// Get the bottom stack frame
var frame = st.GetFrame(st.FrameCount - 1);
// Get the line number from the stack frame
var line = frame.GetFileLineNumber();
var method = frame.GetMethod().ReflectedType.FullName;
var path = frame.GetFileName();
Related