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

  1. Pass a real delegate: () => codeThatShouldThrow();
  2. Fix the helper/fixture that produced the null action.
  3. 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

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


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)