dotnet/reactive · error · ArgumentNullException
removeHandler
Error message
removeHandler
What it means
FromEventPattern throws ArgumentNullException when the removeHandler delegate is null. Both add and remove delegates are required so the observable can unsubscribe and avoid leaks when the observer disposes.
Solutions
- Provide a matching removeHandler delegate, typically (h) => target.EventName -= h
- Verify the same event is used for add and remove so disposal actually detaches
- Check refactored/reflection-based wiring that may produce null for the remove delegate
- If the event genuinely cannot be removed, wrap the handler in a no-op-safe lambda rather than passing null
Example fix
// before
Observable.FromEventPattern<Button, RoutedEventArgs>(
h => button.Click += h,
null);
// after
Observable.FromEventPattern<Button, RoutedEventArgs>(
h => button.Click += h,
h => button.Click -= h); Defensive patterns
Strategy: validation
Validate before calling
if (removeHandler == null) throw new ArgumentNullException(nameof(removeHandler));
Type guard
static bool HasRemoveHandler<T>(Action<T> remove) => remove != null;
Try / catch
try { var obs = Observable.FromEventPattern<TSender, TResult>(add, remove); }
catch (ArgumentNullException ex) when (ex.ParamName == "removeHandler") { /* supply unsubscribe lambda */ } Prevention
- Always pair every += with a corresponding -= in the removeHandler lambda
- Verify disposal removes the handler - write a dispose test
- Avoid conditional compilation that omits unsubscribe logic
- Search for FromEventPattern calls with null second arguments in code review
When it happens
Trigger: Calling Observable.FromEventPattern<TSender,TResult>(addHandler, removeHandler) with a valid addHandler but a null removeHandler Action.
Common situations: Copy-paste wiring code where only the += lambda was written; conditional compilation left the unsubscribe path unimplemented; passing delegates built via reflection where the -='' MethodInfo was not found and null was cached.
Related errors
- addHandler
- conversion
- source
- Value cannot be null. (Parameter 'addHandler')
- Value cannot be null. (Parameter 'removeHandler')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/ab2dd6e98786a8d0.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Platforms/WinRT/Linq/WindowsObservable.Events.cs:35
/// Converts a typed event, conforming to the standard event pattern, to an observable sequence.
/// </summary>
/// <typeparam name="TSender">The type of the sender that raises the event.</typeparam>
/// <typeparam name="TResult">The type of the event data generated by the event.</typeparam>
/// <param name="addHandler">Action that attaches the given event handler to the underlying .NET event.</param>
/// <param name="removeHandler">Action that detaches the given event handler from the underlying .NET event.</param>
/// <returns>The observable sequence that contains data representations of invocations of the underlying typed event.</returns>
/// <exception cref="ArgumentNullException"><paramref name="addHandler"/> or <paramref name="removeHandler"/> is null.</exception>
/// <seealso cref="ToEventPattern"/>
public static IObservable<EventPattern<TSender, TResult>> FromEventPattern<TSender, TResult>(Action<TypedEventHandler<TSender, TResult>> addHandler, Action<TypedEventHandler<TSender, TResult>> removeHandler)
{
if (addHandler == null)
{
throw new ArgumentNullException(nameof(addHandler));
}
if (removeHandler == null)
{
throw new ArgumentNullException(nameof(removeHandler));
}
return Observable.Create<EventPattern<TSender, TResult>>(observer =>
{
var h = new TypedEventHandler<TSender, TResult>((sender, args) =>
{
observer.OnNext(new EventPattern<TSender, TResult>(sender, args));
});
addHandler(h);
return () =>
{
removeHandler(h);
};
});
}
View on GitHub (pinned to 94b5d5ab91)