dotnet/reactive · error · ArgumentNullException
addHandler
Error message
addHandler
What it means
FromEventPattern throws ArgumentNullException when the addHandler delegate used to register a WinRT TypedEventHandler is null. Rx validates both subscription delegates eagerly so event wiring errors appear at operator construction time.
Solutions
- Pass a valid addHandler delegate, typically (h) => target.EventName += h
- Confirm the object whose event is being subscribed is non-null before building the delegate
- Avoid caching delegates in fields that may remain null until initialization completes
- Use a static lambda so the compiler guarantees a non-null delegate instance
Example fix
// before
Action<TypedEventHandler<Button, RoutedEventArgs>> add = null;
Observable.FromEventPattern<Button, RoutedEventArgs>(add, remove);
// after
Observable.FromEventPattern<Button, RoutedEventArgs>(
h => button.Click += h,
h => button.Click -= h); Defensive patterns
Strategy: validation
Validate before calling
if (addHandler == null) throw new ArgumentNullException(nameof(addHandler)); if (removeHandler == null) throw new ArgumentNullException(nameof(removeHandler));
Type guard
static bool CanWireEvents<T>(Action<T> add, Action<T> remove) => add != null && remove != null;
Try / catch
try { var obs = Observable.FromEventPattern<TSender, TResult>(add, remove); }
catch (ArgumentNullException ex) { Log($"Bad event wiring: {ex.ParamName}"); } Prevention
- Always write add/remove as inline lambdas: h => target.Event += h, h => target.Event -= h
- Never cache handler delegates in fields that may be null at wiring time
- Verify the event source object is non-null before FromEventPattern
- Prefer lambda wrappers over reflection-created delegates
When it happens
Trigger: Calling Observable.FromEventPattern<TSender,TResult>(addHandler, removeHandler) with a null addHandler Action<TypedEventHandler<TSender,TResult>>, e.g. passing a method group on an object that was null or a delegate variable that was never assigned.
Common situations: Wiring WinRT UI events through reflection-derived delegates where the MethodInfo lookup returned null; refactoring renamed a handler registration method without updating the delegate reference.
Related errors
- removeHandler
- 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/8652992e0a485c45.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Platforms/WinRT/Linq/WindowsObservable.Events.cs:30
/// </summary>
[CLSCompliant(false)]
public static partial class WindowsObservable
{
/// <summary>
/// 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 () =>
{View on GitHub (pinned to 94b5d5ab91)