dotnet/reactive · error · ArgumentNullException

ArgumentNullException (default message: Value cannot be…

Error message

ArgumentNullException (default message: Value cannot be null. (Parameter 'comparer'))

What it means

The Distinct(source, comparer) overload requires both arguments non-null; this throw site is the comparer == null check that runs after source validation. The comparer is needed to build the internal deduplication set, so the library rejects null eagerly.

Solutions

  1. Pass a valid comparer instance, e.g., EqualityComparer<TSource>.Default for default semantics
  2. Fix the factory/DI registration that was supposed to supply the comparer
  3. If default equality is acceptable, use the comparer-less Distinct() overload instead
  4. Add a null check on the comparer at construction time

Example fix

// before
IEqualityComparer<string> cmp = _comparerProvider?.Get(); // may be null
var result = source.Distinct(cmp);
// after
var result = source.Distinct(cmp ?? EqualityComparer<string>.Default);
Defensive patterns

Strategy: validation

Validate before calling

if (comparer is null) throw new ArgumentNullException(nameof(comparer));
// or: comparer ??= EqualityComparer<TSource>.Default;

Type guard

bool HasComparer<TSource>(IEqualityComparer<TSource>? comparer) => comparer is not null;

Try / catch

try { var result = source.Distinct(comparer); }
catch (ArgumentNullException ex) when (ex.ParamName == "comparer")
{
    result = source.Distinct(); // fall back to default equality
}

Prevention

When it happens

Trigger: Calling Distinct<TSource>(source, null) — a valid source but a null IEqualityComparer<TSource>.

Common situations: A comparer resolved from configuration/DI was not registered, or a custom comparer variable was never assigned before building the query.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs:113

        /// <summary>
        /// Returns an observable sequence that contains only distinct elements according to the comparer.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">An observable sequence to retain distinct elements for.</param>
        /// <param name="comparer">Equality comparer for source elements.</param>
        /// <returns>An observable sequence only containing the distinct elements from the source sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="comparer"/> is null.</exception>
        /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
        public static IObservable<TSource> Distinct<TSource>(this IObservable<TSource> source, IEqualityComparer<TSource> comparer)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (comparer == null)
            {
                throw new ArgumentNullException(nameof(comparer));
            }

            return s_impl.Distinct(source, comparer);
        }

        /// <summary>
        /// Returns an observable sequence that contains only distinct elements according to the keySelector.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TKey">The type of the discriminator key computed for each element in the source sequence.</typeparam>
        /// <param name="source">An observable sequence to retain distinct elements for.</param>
        /// <param name="keySelector">A function to compute the comparison key for each element.</param>
        /// <returns>An observable sequence only containing the distinct elements, based on a computed key value, from the source sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
        /// <remarks>Usage of this operator should be considered carefully due to the maintenance of an internal lookup structure which can grow large.</remarks>
        public static IObservable<TSource> Distinct<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector)
        {
            if (source == null)

View on GitHub (pinned to 94b5d5ab91)