253

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

Liam
  • 27,717
  • 28
  • 128
  • 190
MBZ
  • 26,084
  • 47
  • 114
  • 191
  • at runtime there is no source code. what this line no will be used for? at debug time, the IDE clearly shows line which throws exception. – ankitjaininfo Jul 25 '10 at 11:28
  • possible duplicate of [Exception handling -- display line number where error occurred?](http://stackoverflow.com/questions/2723607/exception-handling-display-line-number-where-error-occurred) – Fredrik Mörk Jul 25 '10 at 11:29
  • 1
    possible duplicate of [Show line number in exception handling](http://stackoverflow.com/questions/688336/show-line-number-in-exception-handling) – Thom Smith Oct 25 '12 at 14:29
  • @ankitjaininfo *not* helpful if there is no IDE! – Michael Aug 19 '19 at 16:55
  • Does this answer your question? [Show line number in exception handling](https://stackoverflow.com/questions/688336/show-line-number-in-exception-handling) – Liam Nov 15 '19 at 14:06

15 Answers15

342

If you need the line number for more than just the formatted stack trace you get from Exception.StackTrace, you can use the StackTrace class:

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();
}

Note that this will only work if there is a pdb file available for the assembly.

Quartermeister
  • 57,579
  • 7
  • 124
  • 111
  • 3
    ?(New StackTrace(ex, True)).GetFrame(0).GetFileLineNumber() for VB single line from the immediate window. – Jonathan Oct 18 '12 at 09:55
  • 44
    C# one liner: `int line = (new StackTrace(ex, true)).GetFrame(0).GetFileLineNumber();` – gunwin Aug 23 '13 at 12:15
  • 24
    This always returns 0 for me. Is this caused by not having a pdb file? What is it and how to get it? (I am using ASP.net) – Brabbeldas Sep 27 '13 at 09:58
  • 20
    Why are you using GetFrame(0)? I would think that you should be using GetFrame(FrameCount-1). – Dewald Swanepoel Jan 15 '15 at 09:24
  • 1
    I voted this up, but in the end I still don't have the line number like Brabbeldas describes. Also substringing from stacktrace and searching for "line :" did not work, does it make a difference if I throw the exceptions my self? Anyway, a null refference is still untraceable for me. – CularBytes Feb 16 '16 at 20:59
  • 2
    This will work depending on where at you are accessing the `StackTrace` - if you are passing the *Exception* around then `.GetFrame(0)` may not be accurate. Just FYI. – Brad Martin Feb 23 '16 at 20:57
  • 13
    I've found @DewaldSwanepoel suggestion of using `GetFrame(st.FrameCount-1)` to be far more reliable. – Brad Martin Feb 23 '16 at 21:03
  • 1
    add `System.Diagnostics;` – zac Feb 07 '17 at 16:35
  • @Brabbeldas I managed to generate PDB files for RELEASE builds by going to Project Properties--> Package/Publish Web --> uncheck Exclude generated debug symbols – Abdul Hameed May 23 '17 at 07:23
  • 1
    PDB file as well as GetFrame(st.FrameCount-1) worked for me – Richard Briggs May 10 '18 at 10:36
  • Seems like GetFrame(#) is not reliable. It would be better to loop through the frames until you find first one that has source. – C.Plock May 03 '23 at 15:51
103

Simple way, use the Exception.ToString() function, it will return the line after the exception description.

You can also check the program debug database as it contains debug info/logs about the whole application.

Otiel
  • 18,404
  • 16
  • 78
  • 126
SimpleButPerfect
  • 1,529
  • 2
  • 11
  • 20
  • Well MSDN thinks differently, that it "Creates and returns a string representation of the current exception": http://msdn.microsoft.com/en-us/library/system.exception.tostring(v=vs.110).aspx – Prokurors Jul 21 '14 at 09:05
  • 1
    You get something similar to: `System.Exception: Test at Tests.Controllers.HomeController.About() in c:\Users\MatthewB\Documents\Visual Studio 2013\Projects\Tests\Tests\Controllers\HomeController.cs:line 22` – Professor of programming Dec 09 '15 at 10:27
  • 5
    This should be the accepted answer. I always went for ex.message and wondered why stupid VB.net isn't able to get the same information as in Java. – Matthis Kohli Apr 08 '16 at 14:45
  • int line = Convert.ToInt32(ex.ToString().Substring(ex.ToString().IndexOf("line")).Replace("line ", "")); – Davy C Mar 16 '17 at 13:25
  • 4
    It is insane that this answer does not have more upvotes. This is simple, works reliably, and does not come with the PDB caveats. – Nick Painter Jun 01 '17 at 15:49
  • 18
    `Exception.Message` is dead to me. Never again. – Reinstate Monica Cellio Mar 09 '18 at 16:31
  • @DavyC wouldn't `int line = Convert.ToInt32(ex.ToString().Substring(ex.ToString().LastIndexOf(" ")));` be better? – Arvo Bowen Jan 16 '20 at 20:33
32

If you don't have the .PBO file:

C#

public int GetLineNumber(Exception ex)
{
    var lineNumber = 0;
    const string lineSearch = ":line ";
    var index = ex.StackTrace.LastIndexOf(lineSearch);
    if (index != -1)
    {
        var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length);
        if (int.TryParse(lineNumberText, out lineNumber))
        {
        }
    }
    return lineNumber;
}

Vb.net

Public Function GetLineNumber(ByVal ex As Exception)
    Dim lineNumber As Int32 = 0
    Const lineSearch As String = ":line "
    Dim index = ex.StackTrace.LastIndexOf(lineSearch)
    If index <> -1 Then
        Dim lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length)
        If Int32.TryParse(lineNumberText, lineNumber) Then
        End If
    End If
    Return lineNumber
End Function

Or as an extentions on the Exception class

public static class MyExtensions
{
    public static int LineNumber(this Exception ex)
    {
        var lineNumber = 0;
        const string lineSearch = ":line ";
        var index = ex.StackTrace.LastIndexOf(lineSearch);
        if (index != -1)
        {
            var lineNumberText = ex.StackTrace.Substring(index + lineSearch.Length);
            if (int.TryParse(lineNumberText, out lineNumber))
            {
            }
        }
        return lineNumber;
    }
}   
radbyx
  • 9,352
  • 21
  • 84
  • 127
23

You could include .PDB symbol files associated to the assembly which contain metadata information and when an exception is thrown it will contain full information in the stacktrace of where this exception originated. It will contain line numbers of each method in the stack.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    How would one go about including a PDB? Is there a way to bundle the PDB into the application / register it to the GAC? –  Jun 09 '20 at 18:24
  • 1
    PDB: https://learn.microsoft.com/en-us/dotnet/core/diagnostics/symbols#learn-about-nets-portable-pdb-format – Mark Schultheiss Mar 02 '23 at 16:07
10

Check this one

StackTrace st = new StackTrace(ex, true);
//Get the first stack frame
StackFrame frame = st.GetFrame(0);

//Get the file name
string fileName = frame.GetFileName();

//Get the method name
string methodName = frame.GetMethod().Name;

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

//Get the column number
int col = frame.GetFileColumnNumber();
Rey
  • 3,663
  • 3
  • 32
  • 55
Ram Maurya
  • 101
  • 1
  • 5
4

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);

    }
}
Nathan
  • 1,303
  • 12
  • 26
vyengr
  • 41
  • 1
4
Convert.ToInt32(ex.StackTrace.Substring(ex.StackTrace.LastIndexOf(' ')));  

This will give the Exception line no.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
3

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#.

Patrice Gahide
  • 3,644
  • 1
  • 27
  • 37
Joseph Michael
  • 167
  • 1
  • 11
2

Update to the answer

    // 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(st.FrameCount-1);
    // Get the line number from the stack frame
    var line = frame.GetFileLineNumber();
Sean Fleming
  • 121
  • 7
1

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);
}
Arvo Bowen
  • 4,524
  • 6
  • 51
  • 109
1

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();
סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
1

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://learn.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();
}
aleksander_si
  • 1,021
  • 10
  • 28
1

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();

0
protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        int line1 = 1;
        int line2 =int.Parse("Test");
    }
    catch (Exception ex)
    {
        var st =new System.Diagnostics.StackTrace(ex,true);
        var frame = st.GetFrame(st.FrameCount - 1);
        var linenumber = frame.GetFileLineNumber();
    }
}
Aydin Kir
  • 1
  • 2
-7

In Global.resx file there is an event called Application_Error

it fires whenever an error occurs,,you can easily get any information about the error,and send it to a bug tracking e-mail.

Also i think all u need to do is to compile the global.resx and add its dll's (2 dlls) to your bin folder and it will work!

Khaled
  • 841
  • 3
  • 13
  • 22