dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'keySelector')
Error message
Value cannot be null. (Parameter 'keySelector')
What it means
In ToDictionary(source, keySelector, valueSelector), the keySelector null check at line 17 throws ArgumentNullException. The key selector produces each dictionary key during aggregation; a null selector would crash mid-stream, so the library rejects it up front. Either selector being null is invalid.
Solutions
- Pass a non-null Func<TSource, TKey> key selector, e.g. x => x.Id.
- Check that the delegate-producing code (DI, reflection, config) actually returns a function.
- Validate both selectors before composing the query.
Example fix
// before Func<Order, int> keySel = null; var dict = orders.ToDictionary(keySel, o => o.Total); // after var dict = orders.ToDictionary(o => o.Id, o => o.Total);
Defensive patterns
Strategy: validation
Validate before calling
if (keySelector is null) throw new ArgumentException("keySelector required");
var dict = source.ToDictionary(keySelector, valueSelector); Type guard
static bool HasKeySelector<T, K>(Func<T, K> k) => k is not null;
Try / catch
try { var d = source.ToDictionary(ks, vs); }
catch (ArgumentNullException ex) when (ex.ParamName == "keySelector") { /* supply selector */ } Prevention
- Write selectors inline (x => x.Id) instead of via nullable delegate fields
- When resolving selectors from config/reflection, fail fast if the delegate is missing
- Add null checks to selector lookup code
When it happens
Trigger: Calling source.ToDictionary(null, valueSelector); passing a selector field that was never assigned.
Common situations: Dynamic query builders where the selector delegate comes from reflection or config and fails to resolve; refactors that renamed a method used as the selector, leaving a null delegate in a dictionary of factories.
Related errors
- Argument cannot be null (Parameter name: functionAsync)
- Argument cannot be null (Parameter name: scheduler)
- ArgumentNullException: durationSelector
- ArgumentNullException: observer
- ArgumentNullException: comparer
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/ea87146ab94b605f.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToDictionary.cs:17
// 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.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<IDictionary<TKey, TValue>> ToDictionary<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<IDictionary<TKey, TValue>>.From(
source,
(keySelector, valueSelector),
static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToDictionary(observer, state.keySelector, state.valueSelector)));
}
public static IAsyncObservable<IDictionary<TKey, TValue>> ToDictionary<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)