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 AsyncObservable.ToHashSet requires a non-null IEqualityComparer<TSource> used to build the internal HashSet and to deduplicate incoming elements. Passing null throws ArgumentNullException(Parameter 'comparer') synchronously at the call site.
Solutions
- Call the parameterless ToHashSet(source) overload when default equality is desired.
- Pass EqualityComparer<TSource>.Default explicitly instead of null.
- Fix the comparer construction so it returns a real instance rather than null.
Example fix
// before var res = source.ToHashSet(comparer); // comparer is null // after var res = comparer != null ? source.ToHashSet(comparer) : source.ToHashSet();
Defensive patterns
Strategy: validation
Validate before calling
if (comparer == null) comparer = EqualityComparer<TSource>.Default;
Type guard
bool IsValidComparer<T>(IEqualityComparer<T> c) => c is not null;
Try / catch
try { var set = await source.ToHashSet(comparer); } catch (ArgumentNullException ex) when (ex.ParamName == "comparer") { /* retry with default comparer */ } Prevention
- Use the parameterless overload when default equality suffices
- Never store comparer dependencies as nullable fields without defaults
- Register custom comparators in DI with non-null defaults
When it happens
Trigger: Calling ToHashSet(source, comparer) with comparer = null, typically a comparer variable that failed to initialize or a ternary that fell through to null.
Common situations: Injecting a comparer via DI that was not registered; loading a comparer from configuration; passing null intending to mean 'use default comparer' instead of calling the parameterless overload.
Related errors
- Value cannot be null. (Parameter 'comparer')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'onNext')
- Value cannot be null. (Parameter 'onError')
- source
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/1d174722d12db036.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToHashSet.cs:24
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<HashSet<TSource>> ToHashSet<TSource>(this IAsyncObservable<TSource> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
return Create<TSource, HashSet<TSource>>(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.ToHashSet(observer)));
}
public static IAsyncObservable<HashSet<TSource>> ToHashSet<TSource>(this IAsyncObservable<TSource> source, IEqualityComparer<TSource> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));
return CreateAsyncObservable<HashSet<TSource>>.From(
source,
comparer,
static (source, comparer, observer) => source.SubscribeSafeAsync(AsyncObserver.ToHashSet(observer, comparer)));
}
}
public partial class AsyncObserver
{
public static IAsyncObserver<TSource> ToHashSet<TSource>(IAsyncObserver<HashSet<TSource>> observer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
return ToHashSet(observer, EqualityComparer<TSource>.Default);
}
View on GitHub (pinned to 94b5d5ab91)