dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'keySelector')
Error message
Value cannot be null. (Parameter 'keySelector')
What it means
The DistinctUntilChanged(source, keySelector) overload requires a non-null Func<TSource,TKey> used to compute comparison keys, and throws ArgumentNullException for a null keySelector. Validation is eager: the exception is thrown when the operator method is invoked, before any element is processed. This prevents a NullReferenceException deep inside the enumeration.
Solutions
- Pass an explicit identity key selector: DistinctUntilChanged(source, x => x) if you intended element comparison.
- If the selector is optional in your API, default it to x => x instead of null before calling.
- Null-check the delegate at your API boundary and throw a descriptive exception.
- Fix the delegate producer (factory/DI/lookup) that returned null.
Example fix
// before Func<Order, int> key = config.Mode == "customer" ? o => o.CustomerId : null; var distinct = orders.DistinctUntilChanged(key); // after Func<Order, int> key = config.Mode == "customer" ? o => o.CustomerId : (Func<Order, int>)(o => o.Id); var distinct = orders.DistinctUntilChanged(key);
Defensive patterns
Strategy: validation
Validate before calling
if (keySelector is null) keySelector = static x => x; // or reject with a clear message var result = source.DistinctUntilChanged(keySelector);
Type guard
static bool HasSelector<TSource,TKey>(Func<TSource,TKey>? f) => f is not null;
Try / catch
try
{
var result = source.DistinctUntilChanged(keySelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "keySelector")
{
result = source.DistinctUntilChanged(x => x);
} Prevention
- Default optional key selectors to x => x instead of null
- Never store 'whole element' intent as a null selector; express it as x => x
- Null-check delegate fields before composing pipelines
- Prefer non-nullable Func<> parameter types on your own APIs to force callers to supply selectors
When it happens
Trigger: Calling DistinctUntilChanged(source, keySelector) where the keySelector lambda/expression reference is null — most often when it is stored in a variable, field, or passed as a method parameter that was null, or a lookup of delegates returns null.
Common situations: Strategy/predicate injection where a delegate was never assigned, overloads confusion (passing null intending to select the whole element), reflection-built pipelines where an optional keySelector defaults to null.
Related errors
- Value cannot be null. (Parameter 'comparer')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'onNext')
- Thrown when source is null (ArgumentNullException, param…
- Thrown when source is null (ArgumentNullException, param…
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/347e088a86aa8c45.
Report an issue: GitHub.
Appendix: source
Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/DistinctUntilChanged.cs:55
throw new ArgumentNullException(nameof(comparer));
return DistinctUntilChangedCore(source, x => x, comparer);
}
/// <summary>
/// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values.
/// </summary>
/// <typeparam name="TSource">Source sequence element type.</typeparam>
/// <typeparam name="TKey">Key type.</typeparam>
/// <param name="source">Source sequence.</param>
/// <param name="keySelector">Key selector.</param>
/// <returns>Sequence without adjacent non-distinct elements.</returns>
public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (keySelector == null)
throw new ArgumentNullException(nameof(keySelector));
return DistinctUntilChangedCore(source, keySelector, EqualityComparer<TKey>.Default);
}
/// <summary>
/// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values.
/// </summary>
/// <typeparam name="TSource">Source sequence element type.</typeparam>
/// <typeparam name="TKey">Key type.</typeparam>
/// <param name="source">Source sequence.</param>
/// <param name="keySelector">Key selector.</param>
/// <param name="comparer">Comparer used to compare key values.</param>
/// <returns>Sequence without adjacent non-distinct elements.</returns>
public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (keySelector == null)View on GitHub (pinned to 94b5d5ab91)