dotnet/reactive · error · ArgumentNullException
ArgumentNullException: action
Error message
ArgumentNullException: action
What it means
WindowsRuntimeThreadPoolScheduler.Schedule<TState> requires a non-null scheduling delegate; it throws ArgumentNullException named 'action' when the Func<IScheduler, TState, IDisposable> passed to schedule work on the WinRT thread pool is null. The library validates up front because a null delegate cannot be wrapped in the UserWorkItem that runs on ThreadPool.RunAsync.
Solutions
- Pass a valid Func<IScheduler, TState, IDisposable> delegate or lambda to Schedule.
- Check any variable holding the delegate for null before calling Schedule.
- If the action may be absent, return a no-op scheduler lambda (e.g. (_, _) => Disposable.Empty) instead of null.
Example fix
// before scheduler.Schedule(state, GetAction()); // GetAction() may return null // after var action = GetAction() ?? ((sch, st) => Disposable.Empty); scheduler.Schedule(state, action);
Defensive patterns
Strategy: validation
Validate before calling
if (action is null) throw new ArgumentNullException(nameof(action)); // or fix at call site: // scheduler.Schedule(state, action ?? ((s, st) => Disposable.Empty));
Type guard
bool IsValidAction<TState>(Func<IScheduler, TState, IDisposable>? a) => a is not null;
Try / catch
try { scheduler.Schedule(state, action); }
catch (ArgumentNullException ex) when (ex.ParamName == "action") { /* supply valid delegate or skip */ } Prevention
- Never return null from delegate factory methods; return no-op lambdas.
- Enable nullable reference types so null delegate flows are caught at compile time.
- Assert delegates non-null in wrapper methods before scheduling.
When it happens
Trigger: Calling scheduler.Schedule(state, null) or passing a null delegate variable/ternary result as the action argument.
Common situations: Delegates built conditionally (e.g. cond ? action1 : null), methods that forward an optional action parameter, or refactored code where the lambda was accidentally removed.
Related errors
- action (Value cannot be null)
- ArgumentNullException (default message: Value cannot be…
- scheduler
- scheduler
- scheduler (Value cannot be null)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/b5c7f71d84a8e215.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive.WindowsRuntime/System.Reactive.Concurrency/WindowsRuntimeThreadPoolScheduler.cs:82
public WorkItemPriority Priority { get; }
/// <summary>
/// Gets the options that configure how work is scheduled.
/// </summary>
public WorkItemOptions Options { get; }
/// <summary>
/// Schedules an action to be executed.
/// </summary>
/// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
/// <param name="state">State passed to the action to be executed.</param>
/// <param name="action">Action to be executed.</param>
/// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
/// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
var userWorkItem = new SystemReactive::System.Reactive.Concurrency.UserWorkItem<TState>(this, state, action);
var res = ThreadPool.RunAsync(
iaa => userWorkItem.Run(),
Priority,
Options);
userWorkItem.CancelQueueDisposable = res.AsDisposable();
return userWorkItem;
}
/// <summary>
/// Schedules an action to be executed after dueTime, using a Windows.System.Threading.ThreadPoolTimer object.
/// </summary>
/// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
/// <param name="state">State passed to the action to be executed.</param>View on GitHub (pinned to 94b5d5ab91)