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
- Pass a valid add delegate, e.g. h => target.MyEvent += h.
- Ensure the target object owning the event is non-null before building the handler lambdas.
- Check that you didn't pass null for the second parameter when using named methods.
- 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
- Write add/remove pairs together: h => t.E += h, h => t.E -= h
- Ensure the event source object exists before creating the observable
- Avoid forwarding nullable delegates through wrapper helpers
- Add unit tests that subscribe and dispose
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)