dotnet/reactive · error · ArgumentNullException

nameof(observer)

Error message

nameof(observer)

What it means

The full Do(observer, onNext, onError, onCompleted) overload throws ArgumentNullException when the observer argument is null. This overload installs separate handlers for each notification kind while forwarding to the observer, so the observer is required and is validated first, before the callback arguments.

Solutions

  1. Provide a non-null observer; if only the three callbacks matter, use AsyncObserver.Create(onNext, onError, onCompleted) as the observer (possibly chained with Do).
  2. Fix the null source: verify the caller of your builder passes a real observer and that DI registration for it exists.
  3. Add a guard or contract check at your own API boundary so null observers fail with a clearer domain message.

Example fix

// before
var obs = AsyncObserver.Do<int>(resolveObserver(), onX, onE, onC); // resolveObserver() returned null

// after
var downstream = resolveObserver() ?? AsyncObserver.Create<int>(_ => default, _ => default, () => default);
var obs = AsyncObserver.Do<int>(downstream, onX, onE, onC);
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null)
    throw new InvalidOperationException("pipeline requires a non-null downstream observer");
var result = AsyncObserver.Do(source, observer, onNext, onError, onCompleted);

Type guard

static bool AllArgsValid<T>(IAsyncObserver<T>? o, Func<T, ValueTask>? n, Func<Exception, ValueTask>? e, Func<ValueTask>? c) => o is not null && n is not null && e is not null && c is not null;

Try / catch

try
{
    var obs = AsyncObserver.Do(source, observer, onNext, onError, onCompleted);
}
catch (ArgumentNullException ex)
{
    log.LogError(ex, "Do composition failed on parameter {Param}", ex.ParamName);
}

Prevention

When it happens

Trigger: Calling AsyncObserver.Do<TSource>(null, onNext, onError, onCompleted) — null first argument even with all three callbacks supplied.

Common situations: Generic pipeline-builder helpers that pass their observer parameter straight through when the caller supplied null; composition happening before the downstream consumer is created in async initialization flows; DI/container resolution silently returning null for the observer dependency.

Related errors


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

Appendix: source

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

                throw new ArgumentNullException(nameof(onError));

            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>(

View on GitHub (pinned to 94b5d5ab91)