runtime: NullReferenceException - Completely devoid of details
I don’t know if this necessarily the right place for this, but the payoff is big enough to warrant a possible failed attempt.
NullReferenceExceptions are the most common exceptions your average developer is going to encounter, and yet the only information that is included in the exception is the message that something was null and you may or may not get a line number in the stacktrace.
Take the following example:
_orderService.CreateOrder(items.ToList(), customer.CustomerId);
If I get a NullReferenceException on this line, there are three different objects that could have been null and caused the error (_orderService, items and customer). Knowing that it was specifically customer that was null would be incredibly helpful. Extending this concept further, having a small dump of all locally scoped variables when the exception was thrown would be incredibly useful, but I’ll go with baby steps and just settle for knowing which variable/expression was the root cause of the null reference exception.
About this issue
- Original URL
- State: open
- Created 9 years ago
- Reactions: 43
- Comments: 45 (21 by maintainers)
Commits related to this issue
- Merge pull request #25 from BruceForstall/LIR6 Reverse argument order of InsertBefore/InsertAfter apis — committed to BruceForstall/coreclr by pgavlin 8 years ago
Is there a plan to also update the exception message? Surely that is really the important part of this?
Has there been any progress on this topic? I think it would be very helpful to introduce more detailed exceptions like Java does. For example code like this.
Java will output a very helpful exception message.
The exact method and reason for the exception are clear at a glance. If there are multiple methods and variables in a line of code, you can quickly locate the problem.
Related: https://openjdk.java.net/jeps/358
JEP 358: Helpful NullPointerExceptions
This feature is indeed available in VS 2017, article says it is not available for .NET Core/UWP, only available for .NET 4.6.2.
Would be really great to have that not in the VS but in .NET Core/Mono so that we can have that information in the crash reports rather than when debugging in VS.
I don’t think that anything that involves crashdumps or WinDBG can be called straightforward. Especially if you consider that NRE is an exception that I think beginners often encounter.
I hope that you are wrong about this. NRE pretty much always indicates a bug and catching it just hides that bug.
Is this available in .Net Core 3.0 ?
It looks like VS 2017 will show the information you want when targeting .NET Framework 4.6.2 or higher: https://blogs.msdn.microsoft.com/devops/2016/03/31/using-the-new-exception-helper-in-visual-studio-15-preview/
I’m not sure whether it’s enabled in .NET Core
The debugger experience is:
But the exception message is unchanged.
This information is not available today. Adding it would be same problem as https://github.com/dotnet/runtime/issues/3858#issuecomment-72954338
@jkotas Is any type information available at the point the exception is generated?
Even if the variable name is unavailable, there are a number of scenarios where knowing the expected type of the null reference would be helpful (even the compile-time type) .
A (very) contrived example:
If the NRE told you the type was
string
, then you’d know the problem wasPostcode
. If it told you that it wasPerson
then it’s ambiguous, but it’s at least narrowed down the possibilities.Obviously it wouldn’t help with something like
Correct, the JIT and PDB do not have enough precision in debug info today to reliably identify the source of NullReferenceException. For example, the following C# statement:
has just one sequence point, and so it is not possible to identify from just the NullReferenceException location and debug info which one of a, b or c was null. If you would like to see the good error message even with JIT optimizations on, it is even harder because of the debug info tracking is not guaranteed to be preserved by the JIT optimizations today.
I think that the first step to attack this problem would be to write a design proposal about possible approaches. The ones identified by @mikedn would be a good start. Focus on:
I know it is a lot of work…
@vongillern I think you can easily make that even better by including the name of the invoked method. Something like (mostly copying the existing message):
This shouldn’t be that hard to do, since the
callvirt
instruction that causes the vast majority of NREs knows which method it was.Agreed. I’m not sure it’d be “easy”, but well worth the effort. If the name was not available, including its type in the error message would make it unambiguous 95% of the time. (i.e. NullReferenceException - expression of type ‘SuperOrderService’ evaluated to null).
My guess though, is that if the PDB is available, it would know the character ranges of the null expression. If i turn on “break on thrown exceptions” in the exceptions dialog box, it always breaks me in at the right point and I can inspect all of my variables. I just want a dump so I don’t have to be actively debugging.