dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'invoke')

Error message

Value cannot be null. (Parameter 'invoke')

What it means

Add also requires the invocation delegate used to raise the event for each emitted EventPattern; null is rejected because the derived class would have no way to invoke the handler. Fix: pass a non-null invocation delegate alongside the handler.

Solutions

  1. Supply the delegate that invokes the handler on the event target (e.g. h => target.Event += h style raise).
  2. Null-check invoke before calling Add.

Example fix

// before
Add(handler, invoke);
// after
Add(handler, invoke ?? (h => { })); // or fix wiring so invoke is real
Defensive patterns

Strategy: validation

Validate before calling

if (invoke == null) throw new ArgumentNullException(nameof(invoke));

Type guard

bool CanAdd<TSender, TArgs>(Action<TSender?, TArgs>? invoke) => invoke is not null;

Try / catch

try { Add(handler, invoke); } catch (ArgumentNullException ex) when (ex.ParamName == "invoke") { /* fix wiring and retry */ }

Prevention

When it happens

Trigger: Calling the protected Add with invoke == null, typically in a derived class whose event-raise action was not initialized or was conditionally created.

Common situations: Custom event adapters where the raise action comes from an optional lambda or reflection-built delegate that failed to build.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/EventPatternSourceBase.cs:109

            _invokeHandler = invokeHandler ?? throw new ArgumentNullException(nameof(invokeHandler));
        }

        /// <summary>
        /// Adds the specified event handler, causing a subscription to the underlying source.
        /// </summary>
        /// <param name="handler">Event handler to add. The same delegate should be passed to the <see cref="Remove(Delegate)"/> operation in order to remove the event handler.</param>
        /// <param name="invoke">Invocation delegate to raise the event in the derived class.</param>
        /// <exception cref="ArgumentNullException"><paramref name="handler"/> or <paramref name="invoke"/> is <c>null</c>.</exception>
        protected void Add(Delegate handler, Action<TSender?, TEventArgs> invoke)
        {
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

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

            var observer = new Observer(this, handler, invoke);
            //
            // [OK] Use of unsafe Subscribe: non-pretentious wrapper of an observable in an event; exceptions can occur during +=.
            //
            observer.SetResource(_source.Subscribe(observer));
        }

        private void Add(Delegate handler, IDisposable disposable)
        {
            lock (_subscriptions)
            {
                if (!_subscriptions.TryGetValue(handler, out var l))
                {
                    _subscriptions[handler] = l = new Stack<IDisposable>();
                }

View on GitHub (pinned to 94b5d5ab91)