dotnet/reactive · error · ArgumentNullException

Argument cannot be null (Parameter name: scheduler)

Error message

Argument cannot be null (Parameter name: scheduler)

What it means

The scheduler-based FromAsync overload throws ArgumentNullException when scheduler is null. FromAsync requires an explicit IAsyncScheduler whenever the two-argument overload is chosen; passing null bypasses the overload's purpose (controlling where the async function runs) and is rejected synchronously.

Solutions

  1. Pass a concrete scheduler, e.g. AsyncObservable.FromAsync(fn, DefaultAsyncScheduler.Instance).
  2. Or use the single-argument overload FromAsync(fn), which schedules with the library default.
  3. Ensure IAsyncScheduler is registered/initialized before building the observable.

Example fix

// before
IAsyncScheduler scheduler = serviceProvider.GetService<IAsyncScheduler>(); // null
var obs = AsyncObservable.FromAsync(fn, scheduler);
// after
var obs = AsyncObservable.FromAsync(fn, DefaultAsyncScheduler.Instance);
Defensive patterns

Strategy: validation

Validate before calling

// C#
var scheduler = injectedScheduler ?? DefaultAsyncScheduler.Instance;
var obs = AsyncObservable.FromAsync(functionAsync, scheduler);

Type guard

static bool HasScheduler(IAsyncScheduler s) => s != null;

Try / catch

try { var obs = AsyncObservable.FromAsync(fn, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { /* use DefaultAsyncScheduler.Instance */ }

Prevention

When it happens

Trigger: Calling AsyncObservable.FromAsync(fn, null) where the scheduler comes from an injectable property, a resolver, or DefaultAsyncScheduler.Instance shadowed by a null field.

Common situations: DI container failing to register IAsyncScheduler so injection yields null; scheduler set later than first use; environment-specific scheduler initialization that was skipped in tests.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromAsync.cs:26

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<ValueTask<TResult>> functionAsync)
        {
            if (functionAsync == null)
                throw new ArgumentNullException(nameof(functionAsync));

            return Defer(() => StartAsync(functionAsync));
        }

        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<ValueTask<TResult>> functionAsync, IAsyncScheduler scheduler)
        {
            if (functionAsync == null)
                throw new ArgumentNullException(nameof(functionAsync));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Defer(() => StartAsync(functionAsync, scheduler));
        }

        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<CancellationToken, ValueTask<TResult>> functionAsync)
        {
            if (functionAsync == null)
                throw new ArgumentNullException(nameof(functionAsync));

            return Defer(() => StartAsync(functionAsync));
        }

        public static IAsyncObservable<TResult> FromAsync<TResult>(Func<CancellationToken, ValueTask<TResult>> functionAsync, IAsyncScheduler scheduler)
        {
            if (functionAsync == null)
                throw new ArgumentNullException(nameof(functionAsync));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

View on GitHub (pinned to 94b5d5ab91)