dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(scheduler));

Error message

throw new ArgumentNullException(nameof(scheduler));

What it means

The Sample<TSource>(source, interval, scheduler) overload throws ArgumentNullException when the scheduler argument is null. The scheduler drives the periodic sampling timer, so the operator requires a concrete IAsyncScheduler; it is checked after source validation.

Solutions

  1. Pass an explicit scheduler such as TaskPoolAsyncScheduler.Default or a local/new async scheduler
  2. When the scheduler is optional, write: scheduler ?? TaskPoolAsyncScheduler.Default
  3. Register the IAsyncScheduler in your DI container / fix the factory returning null
  4. Use the two-argument Sample(source, interval) overload, which defaults to TaskPoolAsyncScheduler.Default

Example fix

// before
var sampled = src.Sample(period, scheduler); // scheduler from DI, may be null
// after
var sampled = src.Sample(period, scheduler ?? TaskPoolAsyncScheduler.Default);
Defensive patterns

Strategy: validation

Validate before calling

if (scheduler is null) scheduler = TaskPoolAsyncScheduler.Default;
var sampled = source.Sample(interval, scheduler);

Type guard

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

Try / catch

try
{
    var sampled = source.Sample(interval, scheduler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler")
{
    sampled = source.Sample(interval, TaskPoolAsyncScheduler.Default);
}

Prevention

When it happens

Trigger: Passing null as the IAsyncScheduler parameter — e.g. a scheduler resolved from configuration/DI that was never registered, a test double left unassigned, or an optional-scheduler code path passing null instead of the default.

Common situations: DI container missing an IAsyncScheduler registration; custom scheduler factory returning null on unsupported platform; migration from another Rx library whose overload defaulted the scheduler.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Sample.cs:58

            return CreateAsyncObservable<TSource>.From(
                source,
                interval,
                static async (source, interval, observer) =>
                {
                    var (sourceSink, sampler) = await AsyncObserver.Sample(observer, interval).ConfigureAwait(false);

                    var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(sourceSubscription, sampler);
                });
        }

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

            return CreateAsyncObservable<TSource>.From(
                source,
                (scheduler, interval),
                static async (source, state, observer) =>
                {
                    var (sourceSink, sampler) = await AsyncObserver.Sample(observer, state.interval, state.scheduler).ConfigureAwait(false);

                    var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(sourceSubscription, sampler);
                });
        }
    }

    public partial class AsyncObserver
    {
        public static (IAsyncObserver<TSource>, IAsyncObserver<TSample>) Sample<TSource, TSample>(IAsyncObserver<TSource> observer)

View on GitHub (pinned to 94b5d5ab91)