dotnet/reactive · error · ArgumentNullException
scheduler (Parameter 'scheduler')
Error message
scheduler (Parameter 'scheduler')
What it means
The public ScheduledItem<TAbsolute, TValue>.ctor(scheduler, state, action, dueTime, comparer) throws ArgumentNullException when scheduler is null. The stored IScheduler is used to invoke (and recursively reschedule) the work item, so it is essential; validation happens after the base comparer check.
Solutions
- Pass the scheduler instance on which the item will run (e.g. 'this' inside a scheduler implementation).
- Fall back to Scheduler.Default or the appropriate scheduler instead of null.
- Add a guard in the code that materializes ScheduledItem instances.
- Fix AsyncLocal/ThreadLocal scheduler resolution so it returns a non-null default.
Example fix
// before var item = new ScheduledItem<DateTimeOffset, int>(currentScheduler /* null */, state, action, dueTime, comparer); // after var scheduler = currentScheduler ?? Scheduler.Default; var item = new ScheduledItem<DateTimeOffset, int>(scheduler, state, action, dueTime, comparer);
Defensive patterns
Strategy: validation
Validate before calling
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler)); Type guard
bool HasScheduler(IScheduler s) => s is not null;
Try / catch
try
{
var item = new ScheduledItem<DateTimeOffset, TState>(scheduler, state, action, dueTime, comparer);
}
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler")
{
var item = new ScheduledItem<DateTimeOffset, TState>(Scheduler.Default, state, action, dueTime, comparer);
} Prevention
- Inside scheduler implementations pass 'this' as the scheduler argument.
- Fall back to Scheduler.Default for ambient-scheduler lookups that can be null.
- Avoid null-returning AsyncLocal/ThreadLocal scheduler providers.
When it happens
Trigger: Constructing ScheduledItem directly (or via custom queue/scheduler code) with a null IScheduler argument, e.g. a scheduler property resolved lazily and still null.
Common situations: Custom PriorityQueue-based schedulers or test harnesses materializing work items; scheduling abstractions where the current scheduler is fetched from AsyncLocal/ThreadLocal storage that is empty; ported code passing null for a scheduler that an older API defaulted.
Related errors
- threadFactory (Parameter 'threadFactory')
- action (Parameter 'action')
- comparer (Parameter 'comparer')
- action (Parameter 'action')
- scheduler (Parameter 'scheduler')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/e450ece3e7dbbc58.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Concurrency/ScheduledItem.cs:185
where TAbsolute : IComparable<TAbsolute>
{
private readonly IScheduler _scheduler;
private readonly TValue _state;
private readonly Func<IScheduler, TValue, IDisposable> _action;
/// <summary>
/// Creates a materialized work item.
/// </summary>
/// <param name="scheduler">Recursive scheduler to invoke the scheduled action with.</param>
/// <param name="state">State to pass to the scheduled action.</param>
/// <param name="action">Scheduled action.</param>
/// <param name="dueTime">Time at which to run the scheduled action.</param>
/// <param name="comparer">Comparer used to compare work items based on their scheduled time.</param>
/// <exception cref="ArgumentNullException"><paramref name="scheduler"/> or <paramref name="action"/> or <paramref name="comparer"/> is <c>null</c>.</exception>
public ScheduledItem(IScheduler scheduler, TValue state, Func<IScheduler, TValue, IDisposable> action, TAbsolute dueTime, IComparer<TAbsolute> comparer)
: base(dueTime, comparer)
{
_scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
_state = state;
_action = action ?? throw new ArgumentNullException(nameof(action));
}
/// <summary>
/// Creates a materialized work item.
/// </summary>
/// <param name="scheduler">Recursive scheduler to invoke the scheduled action with.</param>
/// <param name="state">State to pass to the scheduled action.</param>
/// <param name="action">Scheduled action.</param>
/// <param name="dueTime">Time at which to run the scheduled action.</param>
/// <exception cref="ArgumentNullException"><paramref name="scheduler"/> or <paramref name="action"/> is <c>null</c>.</exception>
public ScheduledItem(IScheduler scheduler, TValue state, Func<IScheduler, TValue, IDisposable> action, TAbsolute dueTime)
: this(scheduler, state, action, dueTime, Comparer<TAbsolute>.Default)
{
}
/// <summary>View on GitHub (pinned to 94b5d5ab91)