dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(scheduler));

Error message

throw new ArgumentNullException(nameof(scheduler));

What it means

The scheduler-based Replay overload (source, selector, bufferSize, window, scheduler) validates the scheduler last and throws ArgumentNullException when it is null. The scheduler is required in this overload because it drives timing of buffered-item expiry, so passing null fails fast.

Solutions

  1. Pass an explicit scheduler instance (e.g. AsyncScheduler.Default) or drop the scheduler argument to use the overload with default timing.
  2. Ensure the IAsyncScheduler is registered and resolvable from your DI container before building the pipeline.
  3. Guard with scheduler ?? AsyncScheduler.Default if null is legitimate in your configuration layer.

Example fix

// before
var replayed = AsyncObservable.Replay(source, sel, 10, window, scheduler: null);
// after
var replayed = AsyncObservable.Replay(source, sel, 10, window, scheduler: AsyncScheduler.Default);
Defensive patterns

Strategy: validation

Validate before calling

if (scheduler is null) throw new InvalidOperationException("Replay with a window requires a non-null scheduler");

Type guard

static bool IsValidScheduler(IAsyncScheduler scheduler) => scheduler is not null;

Try / catch

try { var replayed = AsyncObservable.Replay(source, sel, 10, window, scheduler); } catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { /* pass AsyncScheduler.Default */ }

Prevention

When it happens

Trigger: Calling AsyncObservable.Replay(source, selector, bufferSize, window, null), typically when a scheduler dependency resolved to null or when intending the default scheduler overload and forgetting it needs an explicit instance.

Common situations: DI container missing an IAsyncScheduler registration; a scheduler field assigned asynchronously after pipeline construction; calling the 5-argument overload while intending the 4-argument default-scheduler overload.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Replay.cs:306

                throw new ArgumentOutOfRangeException(nameof(bufferSize));
            if (window < TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(window));

            return Multicast(source, () => new ValueTask<IAsyncSubject<TSource, TSource>>(new SequentialReplayAsyncSubject<TSource>(bufferSize, window)), selector);
        }

        public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, ValueTask<IAsyncObservable<TResult>>> selector, int bufferSize, TimeSpan window, IAsyncScheduler scheduler)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));
            if (bufferSize < 0)
                throw new ArgumentOutOfRangeException(nameof(bufferSize));
            if (window < TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(window));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Multicast(source, () => new ValueTask<IAsyncSubject<TSource, TSource>>(new SequentialReplayAsyncSubject<TSource>(bufferSize, window, scheduler)), selector);
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)