dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'observer')

Error message

Value cannot be null. (Parameter 'observer')

What it means

The capacity-based GroupByUntil overload (observer, subscription, keySelector, durationSelector, capacity) validates each argument and throws ArgumentNullException when observer is null. The observer is the downstream subscriber the operator must forward grouped sequences to; without it the operator cannot function.

Solutions

  1. Pass the actual downstream observer from your subscription pipeline.
  2. Check the pipeline wiring that produced the observer so it is initialized before calling GroupByUntil.
  3. If you must call the operator directly, obtain the observer from a Create/call-operators helper rather than passing null.
Defensive patterns

Strategy: validation

Validate before calling

if (observer == null) throw new InvalidOperationException("GroupByUntil requires a downstream observer");

Type guard

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

Try / catch

try { await GroupByUntil(observer, sub, keySel, durSel, capacity); } catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* fix pipeline wiring / log */ }

Prevention

When it happens

Trigger: Calling GroupByUntil(observer, subscription, keySelector, durationSelector, capacity) with a null IAsyncObserver<TSource>, typically via a delegate or reflection where the observer argument was not supplied.

Common situations: Writing custom query-operator plumbing where the downstream observer variable is null because subscription setup failed, or building operator chains dynamically.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs:488

        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (subscription == null)
                throw new ArgumentNullException(nameof(subscription));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (durationSelector == null)
                throw new ArgumentNullException(nameof(durationSelector));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));

            return GroupByUntil(observer, subscription, keySelector, durationSelector, int.MaxValue, comparer);
        }

        public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, ValueTask<TKey>> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, int capacity)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (subscription == null)
                throw new ArgumentNullException(nameof(subscription));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (durationSelector == null)
                throw new ArgumentNullException(nameof(durationSelector));
            if (capacity < 0)
                throw new ArgumentOutOfRangeException(nameof(capacity));

            return GroupByUntil(observer, subscription, keySelector, durationSelector, capacity, EqualityComparer<TKey>.Default);
        }

        public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, ValueTask<TKey>> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, int capacity, IEqualityComparer<TKey> comparer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (subscription == null)
                throw new ArgumentNullException(nameof(subscription));

View on GitHub (pinned to 94b5d5ab91)