C# ArgumentNullException: value cannot be null
Fix C# ArgumentNullException by tracing the null source, enabling nullable reference types, and guarding public API boundaries.
Symptoms
- System.ArgumentNullException: Value cannot be null. (Parameter x)
- An injected dependency or config value is unexpectedly null
- The exception names a parameter at a deep call site
Possible causes
- A required constructor or method argument was passed null
- A configuration or environment value was not set
- A method returns null where callers assume non-null
- Nullable reference types are disabled, so the compiler cannot warn
Diagnosis steps
Read the parameter name in the message
Interpretation
The parameter name points at the exact argument that arrived null, narrowing the search.
Trace the null to its origin
Interpretation
Follow the argument back to its assignment; often a config read or a helper returns null.
Enable nullable reference types
<Nullable>enable</Nullable>Interpretation
The compiler then flags possible null assignments at build time instead of runtime.
Root cause
ArgumentNullException is thrown when a method requires a non-null argument but receives null. In a nullable-disabled codebase the compiler cannot warn, so nulls flow until a guard deep in the call graph throws, making the reported parameter a symptom rather than the root.
Fix
Enable nullable reference types so the compiler tracks nullability, add ArgumentNullException.ThrowIfNull at public boundaries, and validate configuration at startup so missing values fail fast near their source. Return non-null or a clearly optional type instead of null from helpers.
Verify the fix
Re-run with the previously null value supplied; the exception is gone, and a test asserts the boundary throws ArgumentNullException with the correct parameter name when null is passed.
Symptoms
A method throws ArgumentNullException naming a parameter that the caller believed was set. The reported parameter may be far from where null actually originated.
Diagnosis
Use the parameter name and trace backwards:
public void Send(IMessenger messenger) {
ArgumentNullException.ThrowIfNull(messenger); // fails here
}
Enable nullable types to catch this at compile time.
Fix
Guard boundaries and enable nullability:
#nullable enable
public sealed class Client {
public Client(HttpClient http) {
ArgumentNullException.ThrowIfNull(http);
_http = http;
}
private readonly HttpClient _http;
}
Validate configuration at startup.
Verification
Re-run with the dependency wired up; no ArgumentNullException. A test passes null and asserts the guard throws with the expected parameter name.
Preventing the Next Null
Guarding the throw site is a start, but the durable fix is to make null impossible where it matters. Records and constructors with required members, non-nullable parameters once nullable reference types are enabled, and dependency injection that fails at startup if a service is unregistered all move the failure to the composition root where it is easy to read. Where null is genuinely meaningful, model it with a distinct type or an Option-like result instead of a nullable reference, so every consumer handles the absent case explicitly rather than discovering it at runtime deep in a call stack.