System.NullReferenceException

A NullReferenceException is thrown when your code tries to use a reference that is null, for example by calling a method or reading a property on it. The default message is Object reference not set to an instance of an object. It is one of the most common exceptions in .NET, and it usually points to a bug in your code, not to a problem in the environment.

Minimum version: >= 1.1 >= Core 1.0

Statistics

2
elmah.io logo 4

Common causes

The exception always means the same thing, but there are a few usual ways to end up with a null reference. The examples below assume that nullable reference types are turned off, which is how older projects are set up. More on that further down.

A reference that was never assigned

Fields, properties and array elements of reference types start out as null. If nothing assigns a value before you use them, the first member access throws. The same goes for arrays: new string[3] creates three null strings.

public class OrderService
{
    private List<string> _log;   // never assigned

    public void Add(string line) => _log.Add(line);   // NullReferenceException
}

Assign the field where it is declared, or in the constructor:

public class OrderService
{
    private readonly List<string> _log = new();

    public void Add(string line) => _log.Add(line);
}

Methods such as FirstOrDefault, Find and Array.Find, and casts using as, return null when nothing matches. Using the result without checking it throws.

var customer = customers.FirstOrDefault(c => c.Id == 42);
Console.WriteLine(customer.Name);   // NullReferenceException if no customer has Id 42

Check the result, or use ?. and ??:

var customer = customers.FirstOrDefault(c => c.Id == 42);
Console.WriteLine(customer?.Name ?? "Unknown");

The IConfiguration indexer returns null for a key that is not defined, and so do many other lookups. The exception is thrown on the next line, far away from the missing setting.

var connectionString = configuration["ConnectionString"];
var parts = connectionString.Split(';');   // NullReferenceException if the key is missing

Fail with a message that says what is wrong:

var connectionString = configuration["ConnectionString"]
    ?? throw new InvalidOperationException("ConnectionString is missing.");

Deserializing JSON leaves a property null when the property is missing from the document. The same thing happens with Entity Framework navigation properties that were not loaded, for example because the query has no Include.

var order = JsonSerializer.Deserialize<Order>("""{ "Id": 1 }""");
Console.WriteLine(order.Customer.Name);   // NullReferenceException, Customer is null

Decide what should happen when the object is missing, or handle it with ?.:

var order = JsonSerializer.Deserialize<Order>("""{ "Id": 1 }""");
Console.WriteLine(order?.Customer?.Name ?? "Unknown");

An event with no subscribers is null. Raising it directly throws.

public class Document
{
    public event EventHandler Saved;

    public void Save()
    {
        Saved(this, EventArgs.Empty);   // NullReferenceException if nobody subscribed
    }
}

Raise the event with ?.Invoke:

public class Document
{
    public event EventHandler Saved;

    public void Save()
    {
        Saved?.Invoke(this, EventArgs.Empty);
    }
}

How to fix it and prevent it

Check before you use it

Use a pattern match, the null-conditional operator ?. and the null-coalescing operators ?? and ??= when a value can legitimately be missing.

var customer = customers.FirstOrDefault();

if (customer is not null)
{
    Console.WriteLine(customer.Name);
}

var length = input?.Length ?? 0;

text ??= "default";

When a method cannot work without an argument, reject null at the start with ArgumentNullException.ThrowIfNull. The exception names the parameter, and the next line of the stack trace is the caller that passed the null, instead of failing somewhere deeper inside the method. It is available in .NET 6 and later.

public void Process(Order order)
{
    ArgumentNullException.ThrowIfNull(order);

    // order is safe to use from here
}

With nullable reference types, the compiler tracks which references can be null and warns you before you run the code. Enable it with <Nullable>enable</Nullable> in your project file. New projects created with recent .NET templates have it turned on by default.

static int GetLength(string? input)
{
    return input.Length;   // warning CS8602: Dereference of a possibly null reference.
}

Give fields and collections a value where they are declared, and prefer empty collections and string.Empty over null. In C# 11 and later, required members make the compiler insist that callers set a property.

public class Order
{
    public required Customer Customer { get; init; }
}

How to find the null reference

The stack trace tells you where the exception was thrown. The first line is the method that threw it, with a file name and line number when debug symbols are available:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Shop.Services.OrderService.GetCustomerName(Int32 id) in C:\src\Shop\Services\OrderService.cs:line 10
   at Program.<Main>$(String[] args) in C:\src\Shop\Program.cs:line 4

Line 10 of OrderService.cs is return customer.Name;, so customer was null. The bug is often further up. The next question is why no customer with that id exists, and the second line of the trace shows who asked for it.

If the line contains a chain like order.Customer.Address.City, any link can be the null one. Split the expression into separate statements, or inspect each value in the debugger. Visual Studio's exception helper often names the variable that was null. A long or unreadable trace can be pasted into our Stack Trace Formatter.

Should you catch it?

Usually not. A NullReferenceException is a bug, and catching it hides the bug. Microsoft's own guidance is that it is usually better to avoid the exception than to handle it after it occurs.

Catching makes sense at the edges of your application. A global exception handler, such as UseExceptionHandler in ASP.NET Core, can log the exception and return an error response. A loop that processes many items can log the failing item and continue with the next one. Either way, log the exception, so you can fix the cause.

foreach (var record in records)
{
    try
    {
        Process(record);
    }
    catch (NullReferenceException e)
    {
        logger.LogError(e, "Could not process record {Id}", record.Id);
    }
}

Find NullReferenceException before your users do

elmah.io logs every unhandled exception in your .NET application with its stack trace and request details, groups identical errors and notifies you when a new one appears.

Start free trial
Free 21-day trial No credit card required

Related exceptions

  • ArgumentNullException is thrown by a method that was handed a null argument it does not accept. Throw it yourself to reject null at the boundary.
  • InvalidOperationException is what you get from Nullable<T>.Value when a nullable value type has no value. It is not a NullReferenceException, even though the cause looks similar.

Frequently asked questions

What does "Object reference not set to an instance of an object" mean?

It is the default message of a NullReferenceException. A variable, field, property or array element holds null, and your code used it as if it held an object.

A NullReferenceException is thrown when code uses a null reference. An ArgumentNullException is thrown on purpose by a method that was handed a null argument it does not accept. Throwing it at the start of a method makes the bug show up where the null enters, instead of somewhere deeper.

Start with the line number in the stack trace. If the line contains a chain like order.Customer.Address.City, any part of the chain can be the null one, so split it into separate statements or inspect each value in the debugger. Turning on nullable reference types makes the compiler point out many of these places before you run the code.

Usually it is better not to. A NullReferenceException is a bug in your code, and catching it hides the bug. Catch it only at the edges of your application, such as a global exception handler, and log it so you can fix the cause.

Production has data and configuration that your machine does not: records with missing values, settings that are not defined, requests that skip optional fields. To fix it you need the stack trace and the request that caused it, which is what error logging is for.

Let your AI agent track it down

Connect Claude Code, Cursor, VS Code or Visual Studio to the elmah.io MCP server and ask your agent to look into NullReferenceException for you. For example:

AI chat
Find the most frequent NullReferenceException in my production log and show me the line that throws it.

The agent reads the stack trace and request details from elmah.io, finds the code in your repository and proposes a fix. In Claude Code, add the server with one command:

claude mcp add --transport http --client-id claudecode elmahio https://mcp.elmah.io/mcp

The MCP server is included on every plan and is currently in beta. Set up the MCP server.

Further reading

YouTube videos

Answers from Stack Overflow

I'm not sure what you've tried that is giving you trouble, but you can simply pass in a lambda as the first argument to Assert.Throws. Here's one from one of my tests that passes:

Assert.Throws<ArgumentException>(() => pointStore.Store(new[] { firstPoint }));

Okay, that example may have been a little verbose. Suppose I had a test

[Test]
[ExpectedException("System.NullReferenceException")]
public void TestFoo()
{
    MyObject o = null;
    o.Foo();
}

which would pass normally because o.Foo() would raise a null reference exception.

You then would drop the ExpectedException attribute and wrap your call to o.Foo() in an Assert.Throws.

[Test]
public void TestFoo()
{
    MyObject o = null;
    Assert.Throws<NullReferenceException>(() => o.Foo());
}

Assert.Throws "attempts to invoke a code snippet, represented as a delegate, in order to verify that it throws a particular exception." The () => DoSomething() syntax represents a lambda, essentially an anonymous method. So in this case, we are telling Assert.Throws to execute the snippet o.Foo().

So no, you don't just add a single line like you do an attribute; you need to explicitly wrap the section of your test that will throw the exception, in a call to Assert.Throws. You don't necessarily have to use a lambda, but that's often the most convenient.

By Mark Rushakoff. Read the original answer on Stack Overflow.

Because the language specification expects an expression of type System.Exception there (therefore, null is a valid in that context) and doesn't restrict this expression to be non-null. In general, there's no way it could detect whether the value of that expression is null or not. It would have to solve the halting problem. The runtime will have to deal with the null case anyway. See:

Exception ex = null;
if (conditionThatDependsOnSomeInput) 
    ex = new Exception();
throw ex; 

They could, of course, make the specific case of throwing the null literal invalid but that wouldn't help much, so why waste specification space and reduce consistency for little benefit?

Disclaimer (before I get slapped by Eric Lippert): This is my own speculation about the reasoning behind this design decision. Of course, I haven't been in the design meeting ;)


The answer to your second question, whether an expression variable caught within a catch clause can ever be null: While the C# specification is silent about whether other languages can cause a null exception to be propagated, it does define the way exceptions are propagated:

The catch clauses, if any, are examined in order of appearance to locate a suitable handler for the exception. The first catch clause that specifies the exception type or a base type of the exception type is considered a match. A general catch clause is considered a match for any exception type. [...]

For null, the bold statement is false. So, while purely based on what the C# spec says, we can't say the underlying runtime won't ever throw null, we can be sure that even if that's the case, it'll be only handled by the generic catch {} clause.

For C# implementations on the CLI, we can refer to the ECMA 335 specification. That document defines all exceptions that the CLI throws internally (none of which are null) and mentions that user defined exception objects are thrown by the throw instruction. The description for that instruction is virtually identical to C# throw statement (except that it doesn't restrict the type of the object to System.Exception):

Description:

The throw instruction throws the exception object (type O) on the stack and empties the stack. For details of the exception mechanism, see Partition I.
[Note: While the CLI permits any object to be thrown, the CLS describes a specific exception class that shall be used for language interoperability. end note]

Exceptions:

System.NullReferenceException is thrown if obj is null.

Correctness:

Correct CIL ensures that object is always either null or an object reference (i.e., of type O).

I believe these are sufficient to conclude caught exceptions are never null.

By Mehrdad Afshari. Read the original answer on Stack Overflow.

The correct way in .NET 4.0 is:

if (String.IsNullOrWhiteSpace(strSearch))

The String.IsNullOrWhiteSpace method used above is equivalent to:

if (strSearch == null || strSearch == String.Empty || strSearch.Trim().Length == 0) 
// String.Empty is the same as ""

Reference for IsNullOrWhiteSpace method

http://msdn.microsoft.com/en-us/library/system.string.isnullorwhitespace.aspx

Indicates whether a specified string is Nothing, empty, or consists only of white-space characters.

In earlier versions, you could do something like this:

if (String.IsNullOrEmpty(strSearch) || strSearch.Trim().Length == 0)

The String.IsNullOrEmpty method used above is equivalent to:

if (strSearch == null || strSearch == String.Empty)

Which means you still need to check for your "IsWhiteSpace" case with the .Trim().Length == 0 as per the example.

Reference for IsNullOrEmpty method

http://msdn.microsoft.com/en-us/library/system.string.isnullorempty.aspx

Indicates whether the specified string is Nothing or an Empty string.

Explanation:

You need to ensure strSearch (or any variable for that matter) is not null before you dereference it using the dot character (.) - i.e. before you do strSearch.SomeMethod() or strSearch.SomeProperty you need to check that strSearch != null.

In your example you want to make sure your string has a value, which means you want to ensure the string:

  • Is not null
  • Is not the empty string (String.Empty / "")
  • Is not just whitespace

In the cases above, you must put the "Is it null?" case first, so it doesn't go on to check the other cases (and error) when the string is null.

By Matt Mitchell. Read the original answer on Stack Overflow.

You can add ?? Operator so if ?. returns null task use CompletedTask instead.

await (this.MyObject?.MyMethod() ?? Task.CompletedTask)

I would've expected that the call to "MyMethod" would simply not be made if "MyObject" is null.

Thats true. the ?. operator returns null task instead of calling MyMethod. the null reference exception is made because you cant await on null task. The task must be initialized.

By M.kazem Akhgary. Read the original answer on Stack Overflow.

First off, let me point out that "fire and forget" is almost always a mistake in ASP.NET applications. "Fire and forget" is only an acceptable approach if you don't care whether DeleteFooAsync actually completes.

If you're willing to accept that limitation, I have some code on my blog that will register tasks with the ASP.NET runtime, and it accepts both synchronous and asynchronous work.

You can write a one-time wrapper method for logging exceptions as such:

private async Task LogExceptionsAsync(Func<Task> code)
{
  try
  {
    await code();
  }
  catch(Exception exception)
  {
    m_log.Error("Call failed: " + exception.ToString());
  }
}

And then use the BackgroundTaskManager from my blog as such:

BackgroundTaskManager.Run(() => LogExceptionsAsync(() => DeleteFooAsync()));

Alternatively, you can keep TaskScheduler.UnobservedTaskException and just call it like this:

BackgroundTaskManager.Run(() => DeleteFooAsync());

By Stephen Cleary. Read the original answer on Stack Overflow.