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

  1. Pass a valid addHandler delegate, typically (h) => target.EventName += h
  2. Confirm the object whose event is being subscribed is non-null before building the delegate
  3. Avoid caching delegates in fields that may remain null until initialization completes
  4. 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

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


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)