dotnet/reactive · error · ArgumentNullException

addHandler

Error message

addHandler

What it means

Observable.FromEvent<TDelegate,TEventArgs> throws ArgumentNullException when addHandler is null. addHandler is the delegate that subscribes your constructed handler to the underlying .NET event, so it must be non-null.

Solutions

  1. Pass a valid add delegate, e.g. h => target.MyEvent += h.
  2. Ensure the target object owning the event is non-null before building the handler lambdas.
  3. Check that you didn't pass null for the second parameter when using named methods.
  4. If events come from optional objects, guard the whole subscription in an if (target != null) block.

Example fix

// before
Observable.FromEvent<EventHandler, EventArgs>(conv, null, h => target.MyEvent -= h);
// after
Observable.FromEvent<EventHandler, EventArgs>(conv, h => target.MyEvent += h, h => target.MyEvent -= h);
Defensive patterns

Strategy: validation

Validate before calling

if (addHandler is null) throw new ArgumentNullException(nameof(addHandler)); if (target is null) throw new InvalidOperationException("event source not initialized");

Type guard

bool CanSubscribe<TDelegate>(Action<TDelegate> add) => add is not null;

Prevention

When it happens

Trigger: Calling FromEvent(conversion, null, removeHandler), typically when add/remove delegates are built dynamically or one of them was omitted during refactoring.

Common situations: Conditional subscription setup where only removeHandler was assigned; passing method group of an object that itself was null and '??' defaulted it away incorrectly; typo passing the same variable twice then nulling one.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Events.cs:1177

        /// making the Subscribe or Dispose call, respectively.
        /// </para>
        /// <para>
        /// It's recommended to lift FromEvent calls outside event stream query expressions due to the free-threaded nature of Reactive Extensions. Doing so
        /// makes the captured SynchronizationContext predictable. This best practice also reduces clutter of bridging code inside queries, making the query expressions
        /// more concise and easier to understand.
        /// </para>
        /// </remarks>
        /// <seealso cref="ToEvent"/>
        public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
        {
            if (conversion == null)
            {
                throw new ArgumentNullException(nameof(conversion));
            }

            if (addHandler == null)
            {
                throw new ArgumentNullException(nameof(addHandler));
            }

            if (removeHandler == null)
            {
                throw new ArgumentNullException(nameof(removeHandler));
            }

            return s_impl.FromEvent(conversion, addHandler, removeHandler);
        }

        /// <summary>
        /// Converts a .NET event to an observable sequence, using a conversion function to obtain the event delegate. Each event invocation is surfaced through an OnNext message in the resulting sequence.
        /// For conversion of events conforming to the standard .NET event pattern, use any of the FromEventPattern overloads instead.
        /// </summary>
        /// <typeparam name="TDelegate">The delegate type of the event to be converted.</typeparam>
        /// <typeparam name="TEventArgs">The type of the event data generated by the event.</typeparam>
        /// <param name="conversion">A function used to convert the given event handler to a delegate compatible with the underlying .NET event. The resulting delegate is used in calls to the addHandler and removeHandler action parameters.</param>
        /// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>

View on GitHub (pinned to 94b5d5ab91)