dotnet/reactive · error · ArgumentNullException

onNext

Error message

onNext

What it means

Subscribe<T>(this IObservable<T>, Action<T>) throws ArgumentNullException when the onNext handler is null. The onNext delegate is required to construct the AnonymousObserver (paired with Stubs.Throw for errors and Stubs.Nop for completion). Thrown synchronously after the source check.

Solutions

  1. Pass a non-null onNext lambda, e.g. x => Handle(x).
  2. If no handling is needed, use the parameterless source.Subscribe() overload.
  3. Null-check the handler and fall back to Stubs-style ignore or skip the subscription.

Example fix

// before
source.Subscribe(handler); // handler is null
// after
source.Subscribe(handler ?? (_ => { }));
Defensive patterns

Strategy: validation

Validate before calling

if (onNext == null) return System.Reactive.Disposables.Disposable.Empty;
source.Subscribe(onNext);

Type guard

bool HasHandler<T>(Action<T> onNext) => onNext != null;

Try / catch

try { source.Subscribe(onNext); }
catch (ArgumentNullException ex) when (ex.ParamName == "onNext") { source.Subscribe(_ => { }); }

Prevention

When it happens

Trigger: Calling source.Subscribe(null) or source.Subscribe(someActionVariable) where the Action<T> variable is null — e.g. a handler assigned conditionally or read from config/DI that wasn't set.

Common situations: Event-handler fields that are null until wired; passing a method group that failed to resolve to an overload with a nullable local; factory methods returning null callbacks.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Observable.Extensions.cs:57

        /// <summary>
        /// Subscribes an element handler to an observable sequence.
        /// </summary>
        /// <typeparam name="T">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Observable sequence to subscribe to.</param>
        /// <param name="onNext">Action to invoke for each element in the observable sequence.</param>
        /// <returns><see cref="IDisposable"/> object used to unsubscribe from the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="onNext"/> is <c>null</c>.</exception>
        public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

            //
            // [OK] Use of unsafe Subscribe: non-pretentious constructor for an observer; this overload is not to be used internally.
            //
            return source.Subscribe/*Unsafe*/(new AnonymousObserver<T>(onNext, Stubs.Throw, Stubs.Nop));
        }

        /// <summary>
        /// Subscribes an element handler and an exception handler to an observable sequence.
        /// </summary>
        /// <typeparam name="T">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Observable sequence to subscribe to.</param>
        /// <param name="onNext">Action to invoke for each element in the observable sequence.</param>
        /// <param name="onError">Action to invoke upon exceptional termination of the observable sequence.</param>
        /// <returns><see cref="IDisposable"/> object used to unsubscribe from the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="onNext"/> or <paramref name="onError"/> is <c>null</c>.</exception>
        public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext, Action<Exception> onError)

View on GitHub (pinned to 94b5d5ab91)