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

  1. Pass the scheduler instance on which the item will run (e.g. 'this' inside a scheduler implementation).
  2. Fall back to Scheduler.Default or the appropriate scheduler instead of null.
  3. Add a guard in the code that materializes ScheduledItem instances.
  4. 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

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


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)