dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'keySelector')
Error message
Value cannot be null. (Parameter 'keySelector')
What it means
The comparer overload of Observable.MaxBy throws ArgumentNullException when the keySelector delegate is null. As with all Rx operators, validation happens synchronously at call time via ArgumentNullException(nameof(keySelector)). keySelector defines the key used with the supplied IComparer<TKey> to rank elements.
Solutions
- Pass a concrete key-selection lambda, e.g. source.MaxBy(x => x.Age, comparer).
- Guard the delegate before the call: if (keySelector == null) throw new InvalidOperationException("keySelector required").
- Correct the registration/factory that was supposed to produce the keySelector delegate.
Example fix
// before obs.MaxBy(keyExtractor, myComparer); // keyExtractor is null // after obs.MaxBy(item => item.Key, myComparer);
Defensive patterns
Strategy: validation
Validate before calling
if (source == null || keySelector == null || comparer == null)
throw new ArgumentException("MaxBy requires non-null source, keySelector, and comparer");
var r = source.MaxBy(keySelector, comparer); Type guard
bool ValidForMaxBy<T, TKey>(IObservable<T> s, Func<T, TKey> sel) => s is not null && sel is not null;
Try / catch
try { var r = source.MaxBy(keySelector, comparer); }
catch (ArgumentNullException ex) when (ex.ParamName == "keySelector") { /* provide fallback selector */ } Prevention
- When forwarding parameters through generic helper methods, validate them at the boundary.
- Verify DI/resolver registrations actually produce non-null delegates.
- Prefer inline lambdas over nullable delegate variables for key extraction.
When it happens
Trigger: Calling Observable.MaxBy(source, null, comparer) — the three-argument overload at Observable.Aggregates.cs:1582 with a null keySelector while supplying a comparer.
Common situations: Resolver/DI container returning a null delegate for a registered key-extraction function; a generic helper method whose keySelector parameter was forwarded as null; a nullable Func field not yet initialized at call time.
Related errors
- keySelector
- Value cannot be null. (Parameter 'comparer')
- Value cannot be null. (Parameter 'first')
- Value cannot be null. (Parameter 'second')
- Value cannot be null. (Parameter 'third')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/58434b0b309728d8.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Aggregates.cs:1582
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
/// <typeparam name="TKey">The type of the key computed for each element in the source sequence.</typeparam>
/// <param name="source">An observable sequence to get the maximum elements for.</param>
/// <param name="keySelector">Key selector function.</param>
/// <param name="comparer">Comparer used to compare key values.</param>
/// <returns>An observable sequence containing a list of zero or more elements that have a maximum key value.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
/// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
public static IObservable<IList<TSource>> MaxBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (keySelector == null)
{
throw new ArgumentNullException(nameof(keySelector));
}
if (comparer == null)
{
throw new ArgumentNullException(nameof(comparer));
}
return s_impl.MaxBy(source, keySelector, comparer);
}
#endregion
#region + Min +
/// <summary>
/// Returns the minimum element in an observable sequence.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>View on GitHub (pinned to 94b5d5ab91)