dotnet/reactive · error · ArgumentNullException

observer

Error message

observer

What it means

AsyncObserver.MaxInt64 throws ArgumentNullException with the message 'observer' when the IAsyncObserver<long> argument is null. Like the other typed Max observer factories, it validates its observer argument before building the running-maximum state machine, throwing synchronously at call time.

Solutions

  1. Supply a real IAsyncObserver<long> (AsyncObserver.Create<long>(...) or the pipeline's downstream observer).
  2. Add a null guard in your wrapper so the failure points at the real bug.
  3. Check upstream factories (Select/Where on long streams) for null returns.

Example fix

// before
var obs = AsyncObserver.MaxInt64(observer); // null

// after
var downstream = AsyncObserver.Create<long>(onNext, onError, onCompleted);
var obs = AsyncObserver.MaxInt64(downstream);
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null) throw new InvalidOperationException("MaxInt64 requires a downstream observer");

Type guard

static bool HasLongObserver(IAsyncObserver<long>? o) => o is not null;

Try / catch

try { var obs = AsyncObserver.MaxInt64(observer); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* reconstruct observer */ }

Prevention

When it happens

Trigger: Calling AsyncObserver.MaxInt64(null) — typically a null forwarded from a custom operator or an observer variable that was never initialized.

Common situations: Long-typed aggregation in custom operators where the downstream observer construction was skipped; tests passing null; generic plumbing that erases the observer via a nullable variable.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Max.cs:143

                async () =>
                {
                    if (!found)
                    {
                        await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
                    }
                    else
                    {
                        await observer.OnNextAsync(max).ConfigureAwait(false);
                        await observer.OnCompletedAsync().ConfigureAwait(false);
                    }
                }
            );
        }

        public static IAsyncObserver<long> MaxInt64(IAsyncObserver<long> observer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            var max = 0L;
            var found = false;

            return Create<long>(
                x =>
                {
                    if (found)
                    {
                        if (x > max)
                        {
                            max = x;
                        }
                    }
                    else
                    {
                        max = x;
                        found = true;

View on GitHub (pinned to 94b5d5ab91)