dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'subscribeScheduler')

Error message

Value cannot be null. (Parameter 'subscribeScheduler')

What it means

In the (source, subscribeScheduler, disposeScheduler) overload, the subscribeScheduler null check at line 36 throws ArgumentNullException. The subscribe scheduler is used to schedule the async subscription work (see subscribeScheduler.ScheduleAsync in the body), so null is invalid. Both schedulers must be provided or the shorter overloads used.

Solutions

  1. Pass a non-null IAsyncScheduler for subscribeScheduler (e.g. TaskPoolAsyncScheduler.Default).
  2. If no customization is needed, use source.ToAsyncObservable() which defaults both schedulers.
  3. Use the single-scheduler overload to share one scheduler for subscribe and dispose.

Example fix

// before
var async = source.ToAsyncObservable(null, disposeScheduler);
// after
var async = source.ToAsyncObservable(TaskPoolAsyncScheduler.Default, disposeScheduler);
Defensive patterns

Strategy: validation

Validate before calling

if (subscribeScheduler is null) subscribeScheduler = TaskPoolAsyncScheduler.Default;
var async = source.ToAsyncObservable(subscribeScheduler, disposeScheduler);

Type guard

static bool HasSubscribeScheduler(IAsyncScheduler s) => s is not null;

Try / catch

try { var a = source.ToAsyncObservable(sub, disp); }
catch (ArgumentNullException ex) when (ex.ParamName == "subscribeScheduler") { /* supply scheduler */ }

Prevention

When it happens

Trigger: Calling source.ToAsyncObservable(null, disposeScheduler); passing null explicitly for subscribe-only customization.

Common situations: Attempts to customize only disposal by passing null for subscribe; misconfigured DI binding for IAsyncScheduler.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToAsyncObservable.cs:36

            return ToAsyncObservable(source, TaskPoolAsyncScheduler.Default, TaskPoolAsyncScheduler.Default);
        }

        public static IAsyncObservable<TSource> ToAsyncObservable<TSource>(this IObservable<TSource> source, IAsyncScheduler scheduler)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return ToAsyncObservable(source, scheduler, scheduler);
        }

        public static IAsyncObservable<TSource> ToAsyncObservable<TSource>(this IObservable<TSource> source, IAsyncScheduler subscribeScheduler, IAsyncScheduler disposeScheduler)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (subscribeScheduler == null)
                throw new ArgumentNullException(nameof(subscribeScheduler));
            if (disposeScheduler == null)
                throw new ArgumentNullException(nameof(disposeScheduler));

            return Create<TSource>(async observer =>
            {
                var d = new CompositeAsyncDisposable();

                var subscribeTask = await subscribeScheduler.ScheduleAsync(async ct =>
                {
                    ct.ThrowIfCancellationRequested();

                    var disposable = source.Subscribe(AsyncObserver.ToObserver(observer));

                    var disposeTask = AsyncDisposable.Create(() => disposeScheduler.ExecuteAsync(_ =>
                    {
                        disposable.Dispose();
                        return default;
                    }));

View on GitHub (pinned to 94b5d5ab91)