dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'observer')

Error message

Value cannot be null. (Parameter 'observer')

What it means

This ArgumentNullException is thrown by the internal static Window<TSource> helper (observer, subscription, count) when the downstream IAsyncObserver<IAsyncObservable<TSource>> is null. This helper implements the count-based Window operator's core; it validates the observer, subscription, count, and skip before wiring up the queue of async subjects. A null observer means the operator has nothing to push window observables to.

Solutions

  1. Pass a valid IAsyncObserver<IAsyncObservable<TSource>> (e.g. the observer supplied to your operator's SubscribeAsync).
  2. If calling from a custom operator, forward the observer you received rather than constructing a null.
  3. In tests, provide a stub/mock observer instead of null.
  4. Guard your own code with ArgumentNullException.ThrowIfNull before delegating so the failure surfaces at your boundary.

Example fix

// before
var (winObs, disp) = WindowOperators.Window<TSource>(null, subscription, 5);
// after
var (winObs, disp) = WindowOperators.Window<TSource>(observer, subscription, 5);
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null) throw new ArgumentNullException(nameof(observer));

Type guard

bool IsValidObserver<TSource>(IAsyncObserver<IAsyncObservable<TSource>>? o) => o is not null;

Try / catch

try
{
    var (winObs, disp) = WindowOperators.Window<TSource>(observer, subscription, count);
}
catch (ArgumentNullException ex) when (ex.ParamName == "observer")
{
    throw new InvalidOperationException("Window helper requires a downstream observer.", ex);
}

Prevention

When it happens

Trigger: Calling Window(observer, subscription, count) or Window(observer, subscription, count, skip) with a null observer argument — typically from custom operator plumbing or tests that pass null for the observer.

Common situations: Writing a custom async-Rx operator that composes Window's internals; unit tests exercising the helper with placeholder nulls; refactoring that dropped observer creation before the call.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Window.cs:221

            var d = new SingleAssignmentAsyncDisposable();

            var (sink, subscription) = await createObserverAsync(observer, d).ConfigureAwait(false);

            var inner = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
            await d.AssignAsync(inner).ConfigureAwait(false);

            return subscription;
        }
    }

    public partial class AsyncObserver
    {
        public static (IAsyncObserver<TSource>, IAsyncDisposable) Window<TSource>(IAsyncObserver<IAsyncObservable<TSource>> observer, IAsyncDisposable subscription, int count) => Window(observer, subscription, count, count);

        public static (IAsyncObserver<TSource>, IAsyncDisposable) Window<TSource>(IAsyncObserver<IAsyncObservable<TSource>> observer, IAsyncDisposable subscription, int count, int skip)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (subscription == null)
                throw new ArgumentNullException(nameof(subscription));
            if (count <= 0)
                throw new ArgumentOutOfRangeException(nameof(count));
            if (skip <= 0)
                throw new ArgumentOutOfRangeException(nameof(skip));

            var refCount = new RefCountAsyncDisposable(subscription);

            var queue = new Queue<IAsyncSubject<TSource>>();
            var n = 0;

            return
                (
                    Create<TSource>
                    (
                        async x =>
                        {

View on GitHub (pinned to 94b5d5ab91)