dotnet/reactive · error · ArgumentNullException

ArgumentNullException(nameof(onNext))

Error message

ArgumentNullException(nameof(onNext))

What it means

Do<TSource>(this IAsyncObservable<TSource> source, Action<TSource> onNext) throws ArgumentNullException when the onNext delegate is null. onNext is invoked for every element flowing through the tap; without it the overload is meaningless, so null is rejected at composition time rather than at the first notification.

Solutions

  1. Pass a non-null action, e.g. x => Console.WriteLine(x).
  2. If the tap is optional, skip Do when the action is null: action != null ? source.Do(action) : source.
  3. Ensure configuration/DI providing the callback is set up.

Example fix

// before
source.Do(settings.OnNextHandler); // null when not configured
// after
var action = settings.OnNextHandler ?? throw new InvalidOperationException("onNext handler not configured");
var tapped = source.Do(action);
Defensive patterns

Strategy: validation

Validate before calling

if (onNext is null) throw new InvalidOperationException("onNext callback required");
var tapped = source.Do(onNext);

Type guard

static bool IsValidAction<T>(Action<T>? a) => a is not null;

Try / catch

try { var tapped = source.Do(onNext); }
catch (ArgumentNullException ex) when (ex.ParamName == "onNext") { /* supply a logging/side-effect callback */ }

Prevention

When it happens

Trigger: Calling source.Do(null) or AsyncObservable.Do(source, null) with the Action<TSource> overload; passing an Action variable that was never assigned.

Common situations: Logging action injected from settings that was not configured; a nullable static Action field; a refactor from the IObserver overload leaving the delegate unset.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Do.cs:29

        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, IObserver<TSource> observer)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return Create(
                source,
                observer,
                static (source, observer, target) => source.SubscribeSafeAsync(AsyncObserver.Do(target, observer)));
        }

        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Action<TSource> onNext)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (onNext == null)
                throw new ArgumentNullException(nameof(onNext));

            return Create(
                source,
                onNext,
                static (source, onNext, target) => source.SubscribeSafeAsync(AsyncObserver.Do(target, onNext)));
        }

        public static IAsyncObservable<TSource> Do<TSource>(this IAsyncObservable<TSource> source, Action<Exception> onError)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (onError == null)
                throw new ArgumentNullException(nameof(onError));

            return Create(
                source,
                onError,
                static (source, onError, target) => source.SubscribeSafeAsync(AsyncObserver.Do(target, onError)));

View on GitHub (pinned to 94b5d5ab91)