dotnet/reactive · error · ArgumentNullException
ArgumentNullException: comparer
Error message
ArgumentNullException: comparer
What it means
GroupByUntil uses an IEqualityComparer<TKey> to route elements into groups. The six-argument overload at GroupByUntil.cs:365 throws ArgumentNullException when comparer is null, since the group map cannot compare keys without one.
Solutions
- Pass EqualityComparer<TKey>.Default if no custom comparison is needed
- Implement or register a comparer for the key type and ensure the factory cannot return null
- Drop the comparer argument to use an overload that defaults to the standard comparer
Example fix
// before var res = source.GroupByUntil(k => k, g => g.Take(1), 8, comparer /* null */); // after var res = source.GroupByUntil(k => k, g => g.Take(1), 8, comparer ?? EqualityComparer<TKey>.Default);
Defensive patterns
Strategy: validation
Validate before calling
if (comparer == null) comparer ??= EqualityComparer<TKey>.Default; // normalize before calling
Type guard
bool HasComparer<TKey>(IEqualityComparer<TKey>? c) => c is not null;
Try / catch
try { var res = source.GroupByUntil(keySelector, durationSelector, capacity, comparer); }
catch (ArgumentNullException ex) when (ex.ParamName == "comparer") { /* retry with EqualityComparer<TKey>.Default */ } Prevention
- Default comparer variables to EqualityComparer<TKey>.Default at declaration
- Ensure comparer factories throw rather than return null
- Call comparer-less overloads when custom comparison is not needed
When it happens
Trigger: Calling GroupByUntil(observer, subscription, keySelector, durationSelector, capacity, null) — often because a comparer resolved from DI/config was null, or the code intended a comparer-less overload but extra arguments selected this one.
Common situations: Custom key types whose comparer factory returned null; configurably-supplied comparers in generic pipelines; overload confusion after adding capacity/comparer parameters to a previous call.
Related errors
- ArgumentNullException: durationSelector
- ArgumentNullException: observer
- Argument cannot be null (Parameter name: functionAsync)
- Argument cannot be null (Parameter name: scheduler)
- elementSelector
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/390ed3491afaf009.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs:378
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, 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));
if (keySelector == null)
throw new ArgumentNullException(nameof(keySelector));
if (durationSelector == null)
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);View on GitHub (pinned to 94b5d5ab91)