System.NotImplementedException

A NotImplementedException is thrown by code that was meant to be written later. Visual Studio and other tools generate it when you ask for a method or an interface member to be created, and it stays there until someone replaces it.

In production, it means that a feature is missing, or that a path that was thought to be unused was called. The message is nearly always The method or operation is not implemented, so the stack trace is what tells you which method it was.

Minimum version: >= 1.1 >= Core 1.0

Statistics

26
elmah.io logo 14

Common causes

The exception is not a failure at run time. It is a decision that was never revisited. Typical sources:

A generated stub that was forgotten

The quick fix Generate method and the refactoring Implement interface fill the body with throw new NotImplementedException(). If the method is not used in your own tests, the stub goes live.

public decimal Calculate(decimal amount)
{
    throw new NotImplementedException();
}

Write the method, and cover it with a test, so a stub that is called fails in the build, and not in production:

public decimal Calculate(decimal amount)
{
    return amount * 0.25m;
}

A class that implements an interface with many members, and only needs some, gets stubs for the rest. The caller does not know which members are real.

public interface IExporter
{
    void ExportCsv();
    void ExportPdf();
}

public class CsvExporter : IExporter
{
    public void ExportCsv() { }

    public void ExportPdf() => throw new NotImplementedException();
}

Split the interface, so a class only implements what it can do:

public interface ICsvExporter
{
    void ExportCsv();
}

public interface IPdfExporter
{
    void ExportPdf();
}

public class CsvExporter : ICsvExporter
{
    public void ExportCsv() { }
}

Sometimes a feature is released in steps, and the path for the last step throws. If the user can reach it from the interface, it ends up in your error log.

Hide the feature until it works, or return a clear message to the user. Do not let an exception from a stub reach them.

How to fix it and prevent it

Implement it or remove it

If the method is needed, write it. If nothing calls it, delete it and the interface member behind it. A stub that is never called is only a risk.

A NotImplementedException says not yet. If the type can never support the operation, such as writing to a read-only collection, throw the NotSupportedException with a message that says why.

public void Save() => throw new NotSupportedException("A closed order cannot be saved.");

A search in the source finds them in seconds. Add it to the build, and fail the build when a stub is in code that is shipped.

git grep -n "NotImplementedException" -- "*.cs"

How to read the stack trace

The exception has no information of its own. The top frame is the stub:

System.NotImplementedException: The method or operation is not implemented.
   at Shop.Services.TaxCalculator.Calculate(Decimal amount) in C:\src\Shop\Services\TaxCalculator.cs:line 9
   at Program.<Main>$(String[] args) in C:\src\Shop\Program.cs:line 4

The method is TaxCalculator.Calculate, on line 9 of TaxCalculator.cs. The frame below it shows who called the stub. That caller is the one that expects the feature to exist, so it tells you which part of the product is missing.

Should you catch it?

No. Catching it hides a missing feature. Fix the cause by implementing the method, or by making sure it is never called.

It is fine to catch it in a test that checks which members of a class are still stubs. Nowhere else.

Find NotImplementedException 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

Frequently asked questions

What is the difference between NotImplementedException and NotSupportedException?

The first means that code has not been written yet. The second means that the operation does not make sense for the type, and will never work.

A generated stub was never replaced, and no test or review covered it. Searches for the exception in the code before a release prevent it.

Yes, as a placeholder in your own branch. Do not merge code with stubs on paths that users can reach.

Search for NotImplementedException in your solution, or use the find-in-files of your IDE. A code analyzer can report it as a warning.

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 NotImplementedException for you. For example:

AI chat
Find the most frequent NotImplementedException 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

As long as the object is actually a SkyfilterClient, then a cast should work. Here is a contrived example to prove this:

using System;

class Program
{
    static void Main()
    {
        NetworkClient net = new SkyfilterClient();
        var sky = (SkyfilterClient)net;
    }
}

public class NetworkClient{}
public class SkyfilterClient : NetworkClient{}

However, if it is actually a NetworkClient, then you cannot magically make it become the subclass. Here is an example of that:

using System;

class Program
{
    static void Main()
    {
        NetworkClient net = new NetworkClient();
        var sky = (SkyfilterClient)net;
    }
}

public class NetworkClient{}
public class SkyfilterClient : NetworkClient{}

HOWEVER, you could create a converter class. Here is an example of that, also:

using System;

class Program
{
    static void Main()
    {
        NetworkClient net = new NetworkClient();
        var sky = SkyFilterClient.CopyToSkyfilterClient(net);
    }
}

public class NetworkClient
{  
  public int SomeVal {get;set;}
}

public class SkyfilterClient : NetworkClient
{
    public int NewSomeVal {get;set;}
    public static SkyfilterClient CopyToSkyfilterClient(NetworkClient networkClient)
    {
        return new SkyfilterClient{NewSomeVal = networkClient.SomeVal};
    }
}

But, keep in mind that there is a reason you cannot convert this way. You may be missing key information that the subclass needs.

Finally, if you just want to see if the attempted cast will work, then you can use is:

if(client is SkyfilterClient)
    cast

By Justin Pihony. Read the original answer on Stack Overflow.

An interface can only have public methods. You might consider using an abstract base class with a protected abstract method AddError for this. The base class can then implement the IValidationCRUD interface, but only after you have removed the private method.

like this:

public interface IValidationCRUD
{
    ICRUDValidation IsValid(object obj);
}

public abstract class ValidationCRUDBase: IValidationCRUD {
    public abstract ICRUDValidation IsValid(object obj);
    protected abstract void AddError(ICRUDError error);
}

By Botz3000. Read the original answer on Stack Overflow.

I'm surprised AutoMapper hasn't come up as an answer.

As is clear from all the previous answers, you cannot do the typecast. However, using AutoMapper, in a few lines of code you can have a new SkyfilterClient instantiated based on an existing NetworkClient.

In essence, you would put the following where you are currently doing your typecasting:

using AutoMapper;
...
// somewhere, your network client was declared
var existingNetworkClient = new NetworkClient();
...
// now we want to type-cast, but we can't, so we instantiate using AutoMapper
AutoMapper.Mapper.CreateMap<NetworkClient, SkyfilterClient>();
var skyfilterObject = AutoMapper.Mapper.Map<SkyfilterClient>(existingNetworkClient);

Here's a full-blown example:

  public class Vehicle
  {
    public int NumWheels { get; set; }
    public bool HasMotor { get; set; }
  }

  public class Car: Vehicle
  {
    public string Color { get; set; }
    public string SteeringColumnStyle { get; set; }
  }

  public class CarMaker
  {
    // I am given vehicles that I want to turn into cars...
    public List<Car> Convert(List<Vehicle> vehicles)
    {
      var cars = new List<Car>();
      AutoMapper.Mapper.CreateMap<Vehicle, Car>(); // Declare that we want some automagic to happen
      foreach (var vehicle in vehicles)
      {
        var car = AutoMapper.Mapper.Map<Car>(vehicle);
        // At this point, the car-specific properties (Color and SteeringColumnStyle) are null, because there are no properties in the Vehicle object to map from.
        // However, car's NumWheels and HasMotor properties which exist due to inheritance, are populated by AutoMapper.
        cars.Add(car);
      }
      return cars;
    }
  }

By HeyZiko. Read the original answer on Stack Overflow.

This happens because of NSubstitute syntax specific. For example in:

((IQueryable<Blog>) mockSet).Provider.Returns(data.Provider);

NSubstitute calls the Provider's getter, then it specifies the return value. This getter call isn't intercepted by the substitute and you get an exception. It happens because of explicit implementation of IQueryable.Provider property in DbQuery class.

You can explicitly create substitutes for multiple interfaces with NSub, and it creates a proxy which covers all specified interfaces. Then calls to the interfaces will be intercepted by the substitute. Please use the following syntax:

// Create a substitute for DbSet and IQueryable types:
var mockSet = Substitute.For<DbSet<Blog>, IQueryable<Blog>>();
    
// And then as you do:
((IQueryable<Blog>) mockSet).Provider.Returns(data.Provider);
((IQueryable<Blog>) mockSet).Expression.Returns(data.Expression);
((IQueryable<Blog>) mockSet).ElementType.Returns(data.ElementType);
((IQueryable<Blog>) mockSet).GetEnumerator().Returns(data.GetEnumerator());

By Alexandr Nikitin. Read the original answer on Stack Overflow.

Per the C#9 record proposal, the following should compile, even if not very useful without actual implementations..

// No explicit IEquatable<R> - this is synthesized!
public sealed record SimpleVo
{
    // Not virtual, as SimpleVo (R) is sealed.
    // Accepts SimpleVo? (R?), and not SimpleVo (R), as argument.
    public bool Equals(SimpleVo? other) =>
        throw new System.NotImplementedException();

    // Optional: warning generated if not supplied when Equals(R?) is user-defined. 
    // Must have the override modifier, because System.Object already defines int GetHashCode().
    public override int GetHashCode() =>
        throw new System.NotImplementedException();

    // No other “standard” equality members!
}

There are restrictions on the equality-related members as most of the code is synthesized. The proposal includes examples of the expected synthesized underlying type.

That is, given just a Equals(R?) the compiler creates a ==, !=, and Equals(object). The methods that can be defined can be found by searching for “user-defined” in the proposal.

Attempting to override/define other equality methods or operators is expected to fail:

It is an error if the override is declared explicitly.

The behavior is discussed in ‘Equality members’ and is summarized in the paragraph:

The record type implements System.IEquatable<R> and includes a synthesized strongly-typed overload of bool Equals(R? other) where R is the record type. The method is public, and the method is virtual unless the record type is sealed. The [Equals(R?)] method can be declared explicitly. It is an error if the explicit declaration does not match the expected signature or accessibility, or the explicit declaration doesn't allow overriding it in a derived type and the record type is not sealed. If Equals(R? other) is user-defined (not synthesized) but GetHashCode is not [user-defined], a warning is produced.


By user2864740. Read the original answer on Stack Overflow.