dotnet/reactive · error · ArgumentNullException

nameof(scheduler)

Error message

nameof(scheduler)

What it means

IEnumerable.Subscribe(source, observer, scheduler) throws ArgumentNullException when the IScheduler argument is null. The scheduler controls on which scheduler the enumeration runs; Rx requires a concrete scheduler and validates it last in the wrapper after source and observer.

Solutions

  1. Pass a concrete scheduler such as Scheduler.Default, Scheduler.NewThread, or TaskPoolScheduler.Default.
  2. Default null injected schedulers to Scheduler.Default at the consumption site.
  3. Fix the DI/config registration so the IScheduler binding is always provided.

Example fix

// before
private IScheduler _scheduler; // left null by config
source.Subscribe(observer, _scheduler); // throws
// after
private IScheduler _scheduler = Scheduler.Default;
source.Subscribe(observer, _scheduler);
Defensive patterns

Strategy: validation

Validate before calling

var sched = scheduler ?? Scheduler.Default;
var d = source.Subscribe(observer, sched);

Type guard

static bool HasScheduler(IScheduler? s) => s is not null;

Try / catch

try { var d = source.Subscribe(observer, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { log.Error("Null scheduler; defaulting not applied"); }

Prevention

When it happens

Trigger: Calling source.Subscribe(observer, scheduler) with scheduler == null — e.g. a scheduler injected via an optional constructor parameter that defaulted to null, or Scheduler property not initialized.

Common situations: Happens when configuring test-vs-production schedulers through DI/config: a missing config key leaves the scheduler field null, and the error only surfaces when the subscription is set up.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Conversions.cs:60

        /// <param name="observer">Observer that will receive notifications from the enumerable sequence.</param>
        /// <param name="scheduler">Scheduler to perform the enumeration on.</param>
        /// <returns>Disposable object that can be used to unsubscribe the observer from the enumerable</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="observer"/> or <paramref name="scheduler"/> is null.</exception>
        public static IDisposable Subscribe<TSource>(this IEnumerable<TSource> source, IObserver<TSource> observer, IScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

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

            return s_impl.Subscribe(source, observer, scheduler);
        }

        #endregion

        #region + ToEnumerable +

        /// <summary>
        /// Converts an observable sequence to an enumerable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">An observable sequence to convert to an enumerable sequence.</param>
        /// <returns>The enumerable sequence containing the elements in the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        public static IEnumerable<TSource> ToEnumerable<TSource>(this IObservable<TSource> source)
        {

View on GitHub (pinned to 94b5d5ab91)