dotnet/reactive · error · ArgumentNullException
ArgumentNullException(nameof(keySelector))
Error message
ArgumentNullException(nameof(keySelector))
What it means
ToLookup uses keySelector to group each element under a lookup key. A null keySelector makes grouping impossible, so ArgumentNullException(Parameter 'keySelector') is thrown synchronously at the call site before any subscription occurs.
Solutions
- Supply a concrete key-selector function such as x => x.Key.
- Validate any dynamically chosen selector for null before composing the query.
- Centralize selector construction in a factory that throws a descriptive error instead of returning null.
Example fix
// before var lookup = source.ToLookup(keySelector, x => x.Val); // keySelector null // after var lookup = source.ToLookup(x => x.Key, x => x.Val);
Defensive patterns
Strategy: validation
Validate before calling
if (keySelector == null) throw new ArgumentException("keySelector must be provided", nameof(keySelector)); Type guard
bool IsValidKeySelector<T,TKey>(Func<T,TKey> f) => f is not null;
Try / catch
try { var lookup = await source.ToLookup(keySelector, valueSelector); } catch (ArgumentNullException ex) when (ex.ParamName == "keySelector") { /* supply default selector */ } Prevention
- Define key selectors inline as lambdas rather than nullable delegates
- Validate configuration-driven selector resolution for null
- Keep selector selection logic in a factory that always returns a delegate
When it happens
Trigger: Calling ToLookup(source, null, valueSelector) — e.g. a conditionally assigned key-selector delegate that ended up null.
Common situations: Dynamic query builders where the key selector is chosen per configuration and a missing mapping yields null; reflection-created delegates that failed silently.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- ArgumentNullException(nameof(keySelector))
- ArgumentNullException(nameof(observer))
- ArgumentNullException(nameof(source))
- ArgumentNullException(nameof(valueSelector))
- ArgumentNullException
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/75d36e0bbc5b31d6.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToLookup.cs:18
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<ILookup<TKey, TValue>> ToLookup<TSource, TKey, TValue>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> valueSelector)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (keySelector == null)
throw new ArgumentNullException(nameof(keySelector));
if (valueSelector == null)
throw new ArgumentNullException(nameof(valueSelector));
return CreateAsyncObservable<ILookup<TKey, TValue>>.From(
source,
(keySelector, valueSelector),
static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToLookup(observer, state.keySelector, state.valueSelector)));
}
public static IAsyncObservable<ILookup<TKey, TValue>> ToLookup<TSource, TKey, TValue>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> valueSelector, IEqualityComparer<TKey> comparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (keySelector == null)
throw new ArgumentNullException(nameof(keySelector));
if (valueSelector == null)
throw new ArgumentNullException(nameof(valueSelector));
if (comparer == null)View on GitHub (pinned to 94b5d5ab91)