dotnet/reactive · error · ArgumentNullException

nameof(onNext)

Error message

nameof(onNext)

What it means

The full Do(observer, onNext, onError, onCompleted) overload throws ArgumentNullException when the onNext callback is null. All four arguments are validated in order (observer, onNext, onError, onCompleted) at composition time; onNext fires for every element, so it cannot be null.

Solutions

  1. Supply a non-null onNext handler; if per-element side effects are unnecessary, pass `_ => default`.
  2. Use the null-coalescing idiom `onNext ?? (_ => default)` for optional handlers.
  3. Reorder code so the handler is assigned (or defaulted) before Do is invoked; add a debug assert for early detection.

Example fix

// before
var obs = AsyncObserver.Do<int>(sink, flags.LogElements ? LogAsync : null, onError, onCompleted);

// after
var obs = AsyncObserver.Do<int>(sink, flags.LogElements ? LogAsync : _ => default, onError, onCompleted);
Defensive patterns

Strategy: validation

Validate before calling

onNext ??= _ => default;
var result = AsyncObserver.Do(source, observer, onNext, onError, onCompleted);

Type guard

static bool HasOnNext<T>(Func<T, ValueTask>? h) => h is not null;

Try / catch

try
{
    var obs = AsyncObserver.Do(source, observer, onNext, onError, onCompleted);
}
catch (ArgumentNullException ex) when (ex.ParamName == "onNext")
{
    log.LogError(ex, "onNext was null in full Do overload");
    obs = AsyncObserver.Do(source, observer, _ => default, onError, onCompleted);
}

Prevention

When it happens

Trigger: Calling AsyncObserver.Do<TSource>(validObserver, null, onError, onCompleted) — null Func<TSource, ValueTask> in the four-argument overload.

Common situations: Building handlers from configuration where the per-element handler is optional and left null; passing method groups conditionally compiled or feature-flagged off; a nullable delegate field assigned only in one branch of an if/else.

Related errors


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

Appendix: source

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

            return Do(observer, Create<TSource>(_ => default, onError, () => default));
        }

        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Func<ValueTask> onCompleted)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (onCompleted == null)
                throw new ArgumentNullException(nameof(onCompleted));

            return Do(observer, Create<TSource>(_ => default, _ => default, onCompleted));
        }

        public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Func<TSource, ValueTask> onNext, Func<Exception, ValueTask> onError, Func<ValueTask> onCompleted)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (onNext == null)
                throw new ArgumentNullException(nameof(onNext));
            if (onError == null)
                throw new ArgumentNullException(nameof(onError));
            if (onCompleted == null)
                throw new ArgumentNullException(nameof(onCompleted));

            return Do(observer, Create(onNext, onError, onCompleted));
        }

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

            return Create<TSource>(
                async x =>
                {

View on GitHub (pinned to 94b5d5ab91)