dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'action')
Error message
Value cannot be null. (Parameter 'action')
What it means
ReactiveAssert.Throws<TException>(action) throws ArgumentNullException with parameter name 'action' when the delegate to execute is null. The helper needs a callable Action to run and observe whether it throws TException.
Solutions
- Pass a real delegate: () => codeThatShouldThrow();
- Fix the helper/fixture that produced the null action.
- Guard with a null check or xUnit's Assert.Throws in tests where actions are data-driven.
Example fix
// before
Action act = BuildAction(case); // may be null
ReactiveAssert.Throws<InvalidOperationException>(act);
// after
Action act = BuildAction(case) ?? throw new ArgumentException("missing action for case");
ReactiveAssert.Throws<InvalidOperationException>(act); Defensive patterns
Strategy: validation
Validate before calling
if (action == null)
throw new InvalidOperationException("Action must be provided for Throws assertion");
ReactiveAssert.Throws<InvalidOperationException>(action); Type guard
if (action is not { } validAction) throw new ArgumentException("action is null"); Try / catch
try
{
ReactiveAssert.Throws<ArgumentException>(action);
}
catch (ArgumentNullException ex) when (ex.ParamName == "action")
{
Assert.Fail("Test data missing the action delegate");
} Prevention
- Always pass inline lambdas: () => sut.Call().
- Avoid nullable Action fields in test fixtures.
- Validate data-driven test rows before asserting.
- Prefer Assert.Throws from the test framework when actions are dynamic.
When it happens
Trigger: Passing a null Action to Throws<TException>, commonly from a conditionally assigned delegate variable or a helper that builds the action lazily and returns null on some path.
Common situations: Test parameterization where one row forgot to supply the action; refactors that replaced a lambda with a nullable method reference; dynamic test-case generation producing null delegates.
Related errors
- Value cannot be null. (Parameter 'actual')
- Value cannot be null. (Parameter 'expected')
- ArgumentNullException (default message: Value cannot be…
- ArgumentNullException (default message: Value cannot be…
- ArgumentNullException (default message: Value cannot be…
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/5c2cb79d05fb2ddd.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/Microsoft.Reactive.Testing/ReactiveAssert.cs:210
if (actual == null)
{
throw new ArgumentNullException(nameof(actual));
}
AreElementsEqual(expected.Materialize().ToEnumerable(), actual.Materialize().ToEnumerable(), new NotificationComparer<T>(comparer), message);
}
/// <summary>
/// Asserts that the given action throws an exception of the type specified in the generic parameter, or a subtype thereof.
/// </summary>
/// <typeparam name="TException">Type of the exception to check for.</typeparam>
/// <param name="action">Action to run.</param>
/// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
public static void Throws<TException>(Action action) where TException : Exception
{
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}
var failed = false;
try
{
action();
failed = true;
}
catch (TException)
{
}
catch (Exception ex)
{
Assert.True(false, string.Format(CultureInfo.CurrentCulture, "Expected {0} threw {1}.\r\n\r\nStack trace:\r\n{2}", typeof(TException).Name, ex.GetType().Name, ex.StackTrace));
}
if (failed)
{View on GitHub (pinned to 94b5d5ab91)