dotnet/reactive · error · ArgumentNullException
ArgumentNullException (default message: Value cannot be…
Error message
ArgumentNullException (default message: Value cannot be null. (Parameter 'keySelector'))
What it means
The Distinct(source, keySelector) overload requires a non-null keySelector because Distinct uses it to extract deduplication keys for its internal set; a null keySelector throws ArgumentNullException with Parameter 'keySelector' after source validation passes.
Solutions
- Provide the key selector lambda directly, e.g., x => x.Id
- If you truly need no projection, use the comparer-less Distinct() overload instead of a null selector
- Null-check the selector where it is produced before forwarding
- Fix configuration/DI that should supply the selector
Example fix
// before Func<Item, int> sel = _selector; // may be null var result = source.Distinct(sel); // after var result = source.Distinct(x => x.Id);
Defensive patterns
Strategy: validation
Validate before calling
if (keySelector is null) throw new ArgumentNullException(nameof(keySelector)); // or: keySelector ??= x => x.DefaultKey;
Type guard
bool HasSelector<TSource,TKey>(Func<TSource,TKey>? sel) => sel is not null;
Try / catch
try { var result = source.Distinct(keySelector); }
catch (ArgumentNullException ex) when (ex.ParamName == "keySelector")
{
result = source.Distinct(); // default equality without projection
} Prevention
- Never forward keySelector parameters received as null — validate at the boundary
- Initialize Func fields at declaration or make them required constructor dependencies
- Use a default projection instead of null when the selector is configurable
- Check ex.ParamName to distinguish keySelector from source validation failures
When it happens
Trigger: Calling Distinct<TSource, TKey>(source, null) — valid source, null Func<TSource, TKey>.
Common situations: Storing the key selector in a variable that was never assigned, or receiving it as a null method parameter and forwarding it unchecked.
Related errors
- ArgumentNullException (default message: Value cannot be…
- ArgumentNullException (default message: Value cannot be…
- ArgumentNullException
- first
- keySelector
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/3d975f2b3395b2f3.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs:138
/// 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)
{
throw new ArgumentNullException(nameof(source));
}
if (keySelector == null)
{
throw new ArgumentNullException(nameof(keySelector));
}
return s_impl.Distinct(source, keySelector);
}
/// <summary>
/// Returns an observable sequence that contains only distinct elements according to the keySelector and the comparer.
/// </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>
/// <param name="comparer">Equality comparer for source elements.</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"/> 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, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{View on GitHub (pinned to 94b5d5ab91)