dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(observer));

Error message

throw new ArgumentNullException(nameof(observer));

What it means

AsyncObserver.Return(observer, value, scheduler) writes the single value to the given observer. A null observer gives the scheduled emission no destination, so ArgumentNullException is thrown before the scheduler is touched. It is a defensive guard against a wiring bug.

Solutions

  1. Pass a non-null IAsyncObserver<TSource> as the observer argument.
  2. Use the higher-level AsyncObservable.Return(value) operator, which wires the observer for you.
  3. Fix the observer-producing code path that returns null.

Example fix

// before
AsyncObserver.Return(observer, value); // observer null
// after
var stream = AsyncObservable.Return(value); // let the library wire the observer
await stream.SubscribeAsync(myObserver);
Defensive patterns

Strategy: validation

Validate before calling

if (observer == null) throw new InvalidOperationException("observer required for AsyncObserver.Return");
await AsyncObserver.Return(observer, value);

Type guard

static bool HasObserver<TSource>(IAsyncObserver<TSource> o) => o is not null;

Try / catch

try { await AsyncObserver.Return(observer, value); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* rebuild observer or use AsyncObservable.Return */ }

Prevention

When it happens

Trigger: Calling AsyncObserver.Return<TSource>(null, value) or AsyncObserver.Return<TSource>(null, value, scheduler) — first argument null.

Common situations: Observer obtained from a previous operator's output stored in a nullable field; a subscription helper that forgot to create the observer; passing the result of a method that can return null instead of a real observer.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Return.cs:33

        }

        public static IAsyncObservable<TSource> Return<TSource>(TSource value, IAsyncScheduler scheduler)
        {
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Create<TSource>(observer => AsyncObserver.Return(observer, value, scheduler));
        }
    }

    public partial class AsyncObserver
    {
        public static ValueTask<IAsyncDisposable> Return<TSource>(IAsyncObserver<TSource> observer, TSource value) => Return(observer, value, ImmediateAsyncScheduler.Instance);

        public static ValueTask<IAsyncDisposable> Return<TSource>(IAsyncObserver<TSource> observer, TSource value, IAsyncScheduler scheduler)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return scheduler.ScheduleAsync(async ct =>
            {
                if (ct.IsCancellationRequested)
                    return;

                await observer.OnNextAsync(value).RendezVous(scheduler, ct);

                if (ct.IsCancellationRequested)
                    return;

                await observer.OnCompletedAsync().RendezVous(scheduler, ct);
            });
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)