dotnet/reactive · error · ArgumentNullException

new ArgumentNullException(nameof(scheduler))

Error message

new ArgumentNullException(nameof(scheduler))

What it means

The fully-async Generate overload throws ArgumentNullException when the IAsyncScheduler is null. The scheduler drives ScheduleAsync, iteration delays, and rendezvous continuation; the operator delegates all work to it immediately, so a null scheduler is rejected before any scheduling happens.

Solutions

  1. Pass an explicit scheduler such as TaskPoolAsyncScheduler.Default.
  2. Or call the overload without the scheduler parameter, which defaults to TaskPoolAsyncScheduler.Default (see Generate.cs:342, 428).
  3. Fix the scheduler factory/DI registration so it yields a non-null IAsyncScheduler.

Example fix

// before
Generate(observer, 0, cond, iter, sel, timeSel, null); // throws
// after
Generate(observer, 0, cond, iter, sel, timeSel, TaskPoolAsyncScheduler.Default);
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try { await Generate(observer, state, cond, iter, sel, timeSel, sched); } catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { /* retry with TaskPoolAsyncScheduler.Default */ }

Prevention

When it happens

Trigger: Calling Generate(observer, initialState, condition, iterate, resultSelector, timeSelector, scheduler) (Generate.cs:345) with null for the IAsyncScheduler parameter.

Common situations: A scheduler resolved from DI/configuration that was never registered; passing null to rely on a default that this overload does not have (only the overloads without a scheduler parameter default to TaskPoolAsyncScheduler.Default).

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Generate.cs:358

                throw new ArgumentNullException(nameof(timeSelector));

            return Generate(observer, initialState, condition, iterate, resultSelector, timeSelector, TaskPoolAsyncScheduler.Default);
        }

        public static ValueTask<IAsyncDisposable> Generate<TState, TResult>(IAsyncObserver<TResult> observer, TState initialState, Func<TState, ValueTask<bool>> condition, Func<TState, ValueTask<TState>> iterate, Func<TState, ValueTask<TResult>> resultSelector, Func<TState, ValueTask<TimeSpan>> timeSelector, IAsyncScheduler scheduler)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (condition == null)
                throw new ArgumentNullException(nameof(condition));
            if (iterate == null)
                throw new ArgumentNullException(nameof(iterate));
            if (resultSelector == null)
                throw new ArgumentNullException(nameof(resultSelector));
            if (timeSelector == null)
                throw new ArgumentNullException(nameof(timeSelector));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return scheduler.ScheduleAsync(async ct =>
            {
                var first = true;
                var state = initialState;

                while (!ct.IsCancellationRequested)
                {
                    var hasResult = false;
                    var result = default(TResult);
                    var nextDue = default(TimeSpan);

                    try
                    {
                        if (first)
                        {
                            first = false;
                        }

View on GitHub (pinned to 94b5d5ab91)