dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'elementSelector')

Error message

Value cannot be null. (Parameter 'elementSelector')

What it means

GroupByUntil was called with a null elementSelector Func<TSource, TElement>. The element selector projects each item into its group's element type, and the public factory rejects null for it via ArgumentNullException.

Solutions

  1. Pass an identity projection: x => x.
  2. Provide the actual element projection lambda.
  3. If no element projection is needed, use the overload without elementSelector.
  4. Initialize the delegate field that supplies the selector.

Example fix

// before
source.GroupByUntil(x => x.Key, null, g => g.Close());
// after
source.GroupByUntil(x => x.Key, x => x.Value, g => g.Close());
Defensive patterns

Strategy: validation

Validate before calling

if (elementSelector == null) elementSelector = x => x; // identity projection
source.GroupByUntil(keySelector, elementSelector, durationSelector);

Type guard

static bool HasElementSelector<TSource,TElem>(Func<TSource,TElem>? f) => f is not null;

Try / catch

try { grouped = src.GroupByUntil(ks, es, ds); }
catch (ArgumentNullException ex) when (ex.ParamName == "elementSelector") { grouped = src.GroupByUntil(ks, ds); }

Prevention

When it happens

Trigger: source.GroupByUntil(keySelector, null, durationSelector) — the middle projection argument is null while keySelector and durationSelector are provided.

Common situations: Migrating from the 2-selector-free overload and inserting null as a placeholder, a delegate factory returning null, or conditional element projection left unset.

Related errors


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

Appendix: source

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

            if (capacity < 0)
                throw new ArgumentOutOfRangeException(nameof(capacity));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));

            return CreateAsyncObservable<IGroupedAsyncObservable<TKey, TSource>>.From(
                source,
                (keySelector, durationSelector, capacity, comparer),
                static (source, state, observer) => GroupByUntilCore<TSource, TKey, TSource, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, state.keySelector, state.durationSelector, state.capacity, state.comparer)));
        }

        public static IAsyncObservable<IGroupedAsyncObservable<TKey, TElement>> GroupByUntil<TSource, TKey, TElement, TDuration>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<IGroupedAsyncObservable<TKey, TElement>, IAsyncObservable<TDuration>> durationSelector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (elementSelector == null)
                throw new ArgumentNullException(nameof(elementSelector));
            if (durationSelector == null)
                throw new ArgumentNullException(nameof(durationSelector));

            return CreateAsyncObservable<IGroupedAsyncObservable<TKey, TElement>>.From(
                source,
                (keySelector, elementSelector, durationSelector),
                static (source, state, observer) => GroupByUntilCore<TSource, TKey, TElement, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, state.keySelector, state.elementSelector, state.durationSelector)));
        }

        public static IAsyncObservable<IGroupedAsyncObservable<TKey, TElement>> GroupByUntil<TSource, TKey, TElement, TDuration>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<IGroupedAsyncObservable<TKey, TElement>, IAsyncObservable<TDuration>> durationSelector, IEqualityComparer<TKey> comparer)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (elementSelector == null)
                throw new ArgumentNullException(nameof(elementSelector));
            if (durationSelector == null)

View on GitHub (pinned to 94b5d5ab91)