dotnet/reactive · error · ArgumentNullException

ArgumentNullException

Error message

ArgumentNullException

What it means

AsyncObserver.Create<T>(onNextAsync) requires a non-null onNext delegate and throws ArgumentNullException when it is null. The other two handlers (onError, onCompleted) are defaulted internally, so onNext is the only mandatory argument. The check is synchronous and runs before the observer instance is created.

Solutions

  1. Supply a non-null onNextAsync delegate, e.g. AsyncObserver.Create<T>(async x => { await HandleAsync(x); }).
  2. Check the variable holding the delegate for an unassigned/null value.
  3. If all handlers are dynamic, switch to the full overload Create(onNext, onError, onCompleted) and validate each before calling.

Example fix

// before
AsyncObserver.Create<int>(onNext);
// after
if (onNext == null) onNext = x => new ValueTask(Task.CompletedTask);
AsyncObserver.Create<int>(onNext);
Defensive patterns

Strategy: validation

Validate before calling

if (onNextAsync is null) throw new ArgumentNullException(nameof(onNextAsync));
var observer = AsyncObserver.Create(onNextAsync);

Type guard

bool IsValidHandler<T>(Func<T, ValueTask> f) => f is not null;

Try / catch

try
{
    var observer = AsyncObserver.Create(onNextAsync);
}
catch (ArgumentNullException ex) when (ex.ParamName == "onNextAsync")
{
    // substitute a default onNext or log the configuration bug
}

Prevention

When it happens

Trigger: Calling AsyncObserver.Create<T>(null) — typically Do(observerFactory) passing a null onNext lambda, e.g. x => SomeAsync() where a variable capture resolved to a null delegate.

Common situations: Passing a nullable Func field that was never assigned; using a conditional expression that yields null; calling Create from a generic helper where the delegate parameter defaulted to null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/AsyncObserver.cs:14

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 

using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public static partial class AsyncObserver
    {
        public static IAsyncObserver<T> Create<T>(Func<T, ValueTask> onNextAsync)
        {
            if (onNextAsync == null)
                throw new ArgumentNullException(nameof(onNextAsync));

            return new AsyncObserver<T>(
                onNextAsync,
                ex => new ValueTask(Task.FromException(ex)),
                () => default
            );
        }

        public static IAsyncObserver<T> Create<T>(Func<T, ValueTask> onNextAsync, Func<Exception, ValueTask> onErrorAsync, Func<ValueTask> onCompletedAsync)
        {
            if (onNextAsync == null)
                throw new ArgumentNullException(nameof(onNextAsync));
            if (onErrorAsync == null)
                throw new ArgumentNullException(nameof(onErrorAsync));
            if (onCompletedAsync == null)
                throw new ArgumentNullException(nameof(onCompletedAsync));

            return new AsyncObserver<T>(onNextAsync, onErrorAsync, onCompletedAsync);

View on GitHub (pinned to 94b5d5ab91)