dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'comparer')
Error message
Value cannot be null. (Parameter 'comparer')
What it means
The comparer overload of GroupByUntil requires a non-null IEqualityComparer<TKey> used to bucket elements into groups. A null comparer throws ArgumentNullException at call time in the guard at GroupByUntil.cs:40. Pass EqualityComparer<TKey>.Default when no custom comparison is needed.
Solutions
- Use EqualityComparer<TKey>.Default in place of null
- Ensure the configured/custom comparer is instantiated before the call
- Drop the comparer argument entirely and use the (source, keySelector, durationSelector) overload
Example fix
// before var groups = source.GroupByUntil(x => x.Name, g => g.Take(1), GetComparerOrNull()); // after var cmp = GetComparerOrNull() ?? EqualityComparer<string>.Default; var groups = source.GroupByUntil(x => x.Name, g => g.Take(1), cmp);
Defensive patterns
Strategy: validation
Validate before calling
var cmp2 = comparer ?? EqualityComparer<TKey>.Default;
Type guard
bool HasComparer<TKey>(IEqualityComparer<TKey> c) => c is not null;
Try / catch
try { var groups = source.GroupByUntil(ks, ds, cmp); } catch (ArgumentNullException ex) when (ex.ParamName == "comparer") { var groups = source.GroupByUntil(ks, ds, EqualityComparer<TKey>.Default); } Prevention
- Default comparer providers should return EqualityComparer<T>.Default, never null
- Null-coalesce DI/config-injected comparers at the composition root
- Drop the comparer argument if default equality suffices
When it happens
Trigger: Calling AsyncObservable.GroupByUntil(source, keySelector, durationSelector, (IEqualityComparer<TKey>)null), typically when the comparer comes from an optional settings object that was not populated.
Common situations: Custom comparers injected via DI or configuration returning null when unset, caching an EqualityComparer lookup that missed, or case-insensitive key comparison setup forgotten.
Related errors
- Value cannot be null. (Parameter 'comparer')
- comparer
- ArgumentNullException(nameof(comparer))
- Value cannot be null. (Parameter 'keySelector')
- Value cannot be null. (Parameter 'durationSelector')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/33dc0a5b1114dbeb.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs:40
if (durationSelector == null)
throw new ArgumentNullException(nameof(durationSelector));
return CreateAsyncObservable<IGroupedAsyncObservable<TKey, TSource>>.From(
source,
(keySelector, durationSelector),
static (source, state, observer) => GroupByUntilCore<TSource, TKey, TSource, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, state.keySelector, state.durationSelector)));
}
public static IAsyncObservable<IGroupedAsyncObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, IEqualityComparer<TKey> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
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 CreateAsyncObservable<IGroupedAsyncObservable<TKey, TSource>>.From(
source,
(keySelector, durationSelector, comparer),
static (source, state, observer) => GroupByUntilCore<TSource, TKey, TSource, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, state.keySelector, state.durationSelector, state.comparer)));
}
public static IAsyncObservable<IGroupedAsyncObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, int capacity)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (keySelector == null)
throw new ArgumentNullException(nameof(keySelector));
if (durationSelector == null)
throw new ArgumentNullException(nameof(durationSelector));
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof(capacity));
View on GitHub (pinned to 94b5d5ab91)