My most ridiculous bug of 2025
During my day job at $COMPANY, I was seeing some very perplexing service behavior that could only be explained by a certain property being unexpectedly null. The property in question:
// (C#)
public partial class Controller : IController
{
// (Declared on interface as well)
public RequestContext RequestContext { get; set; }
}
Two strange things about this:
- The property was set at the start of each request and never reassigned:
public IController CreateController(HttpRequestMessage request) { IController controller = new Controller(); controller.RequestContext = new RequestContext(request); // ... return controller; } - Logs corroborated that it was definitely non-null at certain points of the request processing… but not at others.
There’s only a single Controller instance created per request. How can a property that is never reassigned seemingly have fluctuating values?
Snip snap snip snap
After some maddening debugging, the culprit turned out to be in a separate unrelated helper file. Someone had accidentally added a second implementation of the interface property during a large refactor:
// Separate helper file.
public partial class Controller : IController
{
// (A bunch of helper methods on Controller)
// ...
RequestContext IController.RequestContext { get; set; }
}Note the explicit IController.RequestContext property name. With this, the other RequestContext downgraded to a separate Controller-specific property.
Having the same name, resolution depended on whether the object’s type was declared as IController versus Controller (even though the concrete type in non-test code was always Controller). CreateController, operating on an IController, populated the interface one, so:
public partial class Controller : IController
{
public void Test()
{
Test1(this); // True
Test2(this); // False
Test3(); // False
}
public void Test1(IController controller)
{
Console.WriteLine(controller.RequestContext != null);
}
public void Test2(Controller controller)
{
Console.WriteLine(controller.RequestContext != null);
}
public void Test3()
{
Console.WriteLine(this.RequestContext != null);
}
}This explained why the property value appeared to be fluctuating during the processing of the request. Imagine changing a method signature and then getting different behavior. Madness!
Sharp edges everywhere
Surprisingly, this was not the only time I ran into this type of bug. Someone refactored a method and ended up replacing a boolean parameter with a new one of a different purpose. Before:
public partial class Controller : IController
{
public void ProcessRequest(bool useRetries = true)
{
// ...
}
}After:
public partial class Controller : IController
{
public void ProcessRequest(bool validate = false)
{
// ...
}
}Of course, existing callers were updated with some relying on the default parameter. LGTM.
Except this was actually a method defined on the interface but the change forgot to update it there as well. You’d think this would be a compile error — the implementer is now using a different parameter name and default value — but no.
public interface IController
{
void ProcessRequest(bool useRetries = true);
}
public partial class Controller : IController
{
public void TestDefault()
{
this.ProcessRequest(); // Validate: False
((IController)this).ProcessRequest(); // Validate: True
}
public void ProcessRequest(bool validate = false)
{
Console.WriteLine("Validate: " + validate);
}
}Good god…
Anyways, here’s to a happier bug-free 2026!