dotnet/reactive · error · ArgumentNullException

scheduler

Error message

scheduler

What it means

RefCount stays connected while subscriptions exist and uses the scheduler to honor disconnectDelay; a null scheduler leaves the delayed unsubscribe undefined. The parameter name in the message is 'scheduler'. Fix: pass a non-null IScheduler.

Solutions

  1. Pass an explicit scheduler such as Scheduler.Default or Scheduler.ThreadPool
  2. Initialize the scheduler variable/DI binding before calling RefCount
  3. In tests, create the TestScheduler before using it

Example fix

// before
IScheduler sched = null;
var obs = conn.RefCount(TimeSpan.FromSeconds(1), sched);
// after
var obs = conn.RefCount(TimeSpan.FromSeconds(1), Scheduler.Default);
Defensive patterns

Strategy: validation

Validate before calling

if (scheduler == null) scheduler = Scheduler.Default;

Try / catch

try { var obs = conn.RefCount(delay, sched); } catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { sched = Scheduler.Default; }

Prevention

When it happens

Trigger: Calling the scheduler overload with a null scheduler, e.g. an uninitialized scheduler field, a TestScheduler variable not yet assigned, or a DI-resolved scheduler that was null.

Common situations: Unit tests forgetting to instantiate the TestScheduler, configuration-driven scheduler selection returning null, or refactors removing Scheduler.Default.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/b65db6b99a903d04. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Binding.cs:283

        /// <summary>
        /// Returns an observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Connectable observable sequence.</param>
        /// <param name="disconnectDelay">The time span that should be waited before possibly unsubscribing from the connectable observable.</param>
        /// <param name="scheduler">The scheduler to use for delayed unsubscription.</param>
        /// <returns>An observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        public static IObservable<TSource> RefCount<TSource>(this IConnectableObservable<TSource> source, TimeSpan disconnectDelay, IScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            if (disconnectDelay < TimeSpan.Zero)
            {
                throw new ArgumentException("Delay cannot be less than zero", nameof(disconnectDelay));
            }

            return s_impl.RefCount(source, disconnectDelay, scheduler);
        }

        /// <summary>
        /// Returns an observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Connectable observable sequence.</param>
        /// <param name="minObservers">The minimum number of observers required to subscribe before establishing the connection to the source.</param>
        /// <returns>An observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>

View on GitHub (pinned to 94b5d5ab91)