dotnet/reactive · error · ArgumentNullException

scheduler

Error message

scheduler

What it means

System.ArgumentNullException with param name 'scheduler'. This overload of FromEventPattern takes an explicit IAsyncScheduler to control where subscription/dispatch runs, and the null check throws immediately if scheduler is null. The library does not fall back to a default in this overload by design.

Solutions

  1. Pass a valid IAsyncScheduler instance, e.g. AsyncScheduler.Default or your configured test scheduler.
  2. Drop the third argument entirely to use the overload that resolves the scheduler from the current context.
  3. If the scheduler comes from DI/configuration, verify it is registered and non-null before the call.
  4. Guard with an ArgumentNullException.ThrowIfNull-style check at your call site to get a clearer stack trace.

Example fix

// before
var obs = AsyncObservable.FromEventPattern(
    h => target.Something += h,
    h => target.Something -= h,
    null);
// after
var obs = AsyncObservable.FromEventPattern(
    h => target.Something += h,
    h => target.Something -= h,
    AsyncScheduler.Default);
Defensive patterns

Strategy: validation

Validate before calling

if (scheduler == null) scheduler = AsyncScheduler.Default; // or omit the parameter entirely

Type guard

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

Try / catch

try
{
    var obs = AsyncObservable.FromEventPattern(add, remove, scheduler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler")
{
    // fall back or fix scheduler initialization
}

Prevention

When it happens

Trigger: Calling FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler, IAsyncScheduler scheduler) with a null scheduler, e.g. FromEventPattern(h => e.AddHandler(h), h => e.RemoveHandler(h), null) or passing a scheduler variable that was never initialized.

Common situations: A scheduler obtained from a factory or DI container is null (failed resolution), or the developer meant to call the two-argument overload (which uses GetSchedulerForCurrentContext()) but included a trailing null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEventPattern.cs:25

using System.Reactive.Disposables;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<EventPattern<object>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler) => FromEventPattern(addHandler, removeHandler, GetSchedulerForCurrentContext());

        public static IAsyncObservable<EventPattern<object>> FromEventPattern(Action<EventHandler> addHandler, Action<EventHandler> 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 FromEvent<EventHandler, object, EventArgs>(
                action => new EventHandler((o, e) => action(o, e)),
                addHandler,
                removeHandler,
                scheduler).Select(t => new EventPattern<object>(t.arg1, t.arg2));
        }

        public static IAsyncObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler) => FromEventPattern<TDelegate, TEventArgs>(addHandler, removeHandler, GetSchedulerForCurrentContext());

        public static IAsyncObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> 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));

View on GitHub (pinned to 94b5d5ab91)