dotnet/reactive · error · ArgumentNullException

scheduler

Error message

scheduler

What it means

AsyncObservable.FromEvent threw ArgumentNullException because the scheduler argument was null. This overload accepts an explicit IAsyncScheduler used to coordinate event subscription and unsubscription. The library requires a concrete scheduler; pass AsyncScheduler.Default (or a specific scheduler) when you do not need custom scheduling.

Solutions

  1. Pass AsyncScheduler.Default (or the scheduler appropriate for your concurrency model) as the third argument.
  2. Use the shorter overload FromEvent<TEventArgs>(addHandler, removeHandler), which obtains a scheduler from the current context automatically.
  3. If the scheduler comes from DI/configuration, assert or default it before the call: scheduler ?? AsyncScheduler.Default.

Example fix

// before
var obs = AsyncObservable.FromEvent<EventArgs>(
    h => target.TheEvent += h,
    h => target.TheEvent -= h,
    null);
// after
var obs = AsyncObservable.FromEvent<EventArgs>(
    h => target.TheEvent += h,
    h => target.TheEvent -= h,
    AsyncScheduler.Default);
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try
{
    var obs = AsyncObservable.FromEvent<EventArgs>(addHandler, removeHandler, scheduler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler")
{
    obs = AsyncObservable.FromEvent<EventArgs>(addHandler, removeHandler);
}

Prevention

When it happens

Trigger: Calling FromEvent<TEventArgs>(addHandler, removeHandler, null) with a null IAsyncScheduler while both handler delegates are non-null.

Common situations: Developers resolving the scheduler from DI or a config value that is null (e.g. an unbound optional service), or copying a code sample and leaving the scheduler parameter unfilled.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEvent.cs:31

    {
        public static IAsyncObservable<TEventArgs> FromEvent<TEventArgs>(Action<Action<TEventArgs>> addHandler, Action<Action<TEventArgs>> removeHandler)
        {
            if (addHandler == null)
                throw new ArgumentNullException(nameof(addHandler));
            if (removeHandler == null)
                throw new ArgumentNullException(nameof(removeHandler));

            return FromEventCore<Action<TEventArgs>, TEventArgs>(h => h, addHandler, removeHandler, GetSchedulerForCurrentContext());
        }

        public static IAsyncObservable<TEventArgs> FromEvent<TEventArgs>(Action<Action<TEventArgs>> addHandler, Action<Action<TEventArgs>> removeHandler, IAsyncScheduler scheduler)
        {
            if (addHandler == null)
                throw new ArgumentNullException(nameof(addHandler));
            if (removeHandler == null)
                throw new ArgumentNullException(nameof(removeHandler));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return FromEventCore<Action<TEventArgs>, TEventArgs>(h => h, addHandler, removeHandler, scheduler);
        }

        public static IAsyncObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
        {
            if (addHandler == null)
                throw new ArgumentNullException(nameof(addHandler));
            if (removeHandler == null)
                throw new ArgumentNullException(nameof(removeHandler));

            return FromEventCore<TDelegate, TEventArgs>(h => ConvertDelegate<Action<TEventArgs>, TDelegate>(h), addHandler, removeHandler, GetSchedulerForCurrentContext());
        }

        public static IAsyncObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IAsyncScheduler scheduler)
        {
            if (addHandler == null)
                throw new ArgumentNullException(nameof(addHandler));

View on GitHub (pinned to 94b5d5ab91)