dotnet/reactive · error · ArgumentNullException
ArgumentNullException: elementSelector
Error message
ArgumentNullException: elementSelector
What it means
GroupByUntil throws ArgumentNullException when elementSelector is null. The elementSelector projects each source element into the element emitted by the grouped observable; without it the operator cannot construct groups. The library validates arguments eagerly so the failure points at the caller rather than inside the async pipeline.
Solutions
- Pass an identity projection if no transformation is needed: o => o.
- Supply the actual projection lambda, e.g. o => o.Lines.
- Default an optional selector: elementSelector ?? (x => x).
- Verify parameter order — keySelector, elementSelector, durationSelector — in the overload you call.
Example fix
// before var groups = source.GroupByUntil(o => o.Type, null, g => g.TakeUntil(done)); // after var groups = source.GroupByUntil(o => o.Type, o => o, g => g.TakeUntil(done));
Defensive patterns
Strategy: validation
Validate before calling
if (elementSelector == null) throw new InvalidOperationException("GroupByUntil requires a non-null elementSelector; use o => o for identity");
var groups = source.GroupByUntil(keySelector, elementSelector, durationSelector); Type guard
static bool IsValidSelector<TSource,TElement>(Func<TSource,TElement> f) => f is not null;
Try / catch
try
{
var groups = source.GroupByUntil(keySelector, elementSelector, durationSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "elementSelector")
{
// substitute identity projection and retry
} Prevention
- Use o => o explicitly when no projection is needed — never null.
- Memorize the parameter order: keySelector, elementSelector, durationSelector.
- Coalesce optional projections: elementSelector ?? (x => x).
- Review call sites after overload refactors.
When it happens
Trigger: Calling a public GroupByUntil overload at GroupByUntil.cs:392 (the 3-delegate overload forwarding to the full overload with int.MaxValue capacity and default comparer) with null as the elementSelector argument.
Common situations: Passing null instead of an identity lambda (o => o) when no element projection is needed; a projection delegate variable left null after conditional setup; misuse of an overload whose parameter order was misread.
Related errors
- Value cannot be null. (Parameter 'elementSelector')
- observer
- subscription
- keySelector
- Value cannot be null. (Parameter 'selector')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/b25a3795743ad88a.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs:392
throw new ArgumentNullException(nameof(durationSelector));
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof(capacity));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));
return GroupByUntil(observer, subscription, x => new ValueTask<TKey>(keySelector(x)), durationSelector, capacity, comparer);
}
public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TElement, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TElement>> observer, IAsyncDisposable subscription, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<IGroupedAsyncObservable<TKey, TElement>, IAsyncObservable<TDuration>> durationSelector)
{
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 (elementSelector == null)
throw new ArgumentNullException(nameof(elementSelector));
if (durationSelector == null)
throw new ArgumentNullException(nameof(durationSelector));
return GroupByUntil(observer, subscription, keySelector, elementSelector, durationSelector, int.MaxValue, EqualityComparer<TKey>.Default);
}
public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TElement, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TElement>> observer, IAsyncDisposable subscription, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<IGroupedAsyncObservable<TKey, TElement>, IAsyncObservable<TDuration>> durationSelector, IEqualityComparer<TKey> comparer)
{
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 (elementSelector == null)
throw new ArgumentNullException(nameof(elementSelector));
if (durationSelector == null)
throw new ArgumentNullException(nameof(durationSelector));View on GitHub (pinned to 94b5d5ab91)