dotnet/reactive · error · ArgumentNullException

addHandler

Error message

addHandler

What it means

FromEventPattern(addHandler, removeHandler, scheduler) validates arguments in order; this error means addHandler (an Action<EventHandler>) was null. Since FromEventPattern forwards to FromEvent<EventHandler, object, EventArgs>, the null addHandler makes the event subscription impossible and the guard throws ArgumentNullException with ParamName "addHandler".

Solutions

  1. Pass the event's add accessor: h => src.Clicked += h.
  2. Use the string/EventInfo-based FromEventPattern overloads when wiring via reflection, which resolve accessors for you.
  3. Verify add/remove arguments are in the right order and the source object is initialized.

Example fix

// before
var sub = AsyncRx.Observable.FromEventPattern(null, h => src.Clicked -= h);
// after
var sub = AsyncRx.Observable.FromEventPattern(h => src.Clicked += h, h => src.Clicked -= h);
Defensive patterns

Strategy: validation

Validate before calling

if (addHandler == null || removeHandler == null) throw new ArgumentException("Both addHandler and removeHandler are required, e.g. h => src.Clicked += h / h => src.Clicked -= h");

Type guard

bool CanSubscribePattern(Action<EventHandler> addHandler, Action<EventHandler> removeHandler) => addHandler != null && removeHandler != null;

Try / catch

try { var sub = FromEventPattern(add, remove); }
catch (ArgumentNullException ex) when (ex.ParamName == "addHandler") { /* check argument order and source initialization */ }

Prevention

When it happens

Trigger: Calling FromEventPattern(null, removeHandler) or FromEventPattern(null, removeHandler, scheduler), e.g. FromEventPattern(null, h => src.Event -= h).

Common situations: Reflection overloads (FromEventPattern(name)) resolved elsewhere but here wiring delegates directly from a lookup table where the add entry is missing; swapping add/remove by mistake; event source obtained from an uninitialized control so the accessor lambda was never built.

Related errors


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

Appendix: source

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

// See the LICENSE file in the project root for more information. 

using System.Globalization;
using System.Reactive.Concurrency;
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));

View on GitHub (pinned to 94b5d5ab91)