dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'valueSelector')
Error message
Value cannot be null. (Parameter 'valueSelector')
What it means
System.Reactive.Async's ToDictionary extension validates all arguments up front and throws ArgumentNullException when the valueSelector Func<TSource,TValue> is null. The library eagerly guards operators so failures surface at call time rather than during async subscription. Passing a null valueSelector means the operator could never project values into the dictionary.
Solutions
- Pass a non-null value selector lambda, e.g. source.ToDictionary(x => x.Key, x => x.Value).
- If the selector is optional, supply a default such as x => x before calling.
- If selection can fail, throw a meaningful exception inside the lambda instead of passing null.
Example fix
// before var dict = await source.ToDictionary(x => x.Id, (Func<Order, decimal>)null); // after var dict = await source.ToDictionary(x => x.Id, x => x.Total);
Defensive patterns
Strategy: validation
Validate before calling
if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); if (valueSelector == null) throw new ArgumentNullException(nameof(valueSelector)); var dict = await source.ToDictionary(keySelector, valueSelector);
Type guard
static bool IsValidSelectors<TSource,TKey,TValue>(Func<TSource,TKey> k, Func<TSource,TValue> v) => k != null && v != null;
Try / catch
try { var dict = await source.ToDictionary(keySelector, valueSelector); }
catch (ArgumentNullException ex) when (ex.ParamName == "valueSelector") { /* supply default selector or log */ } Prevention
- Never assign null to Func/ValueTask delegate variables; default to identity lambdas.
- Let the compiler infer lambdas inline instead of casting null to delegate types.
- Add Debug.Assert(selector != null) where selectors are built dynamically.
When it happens
Trigger: Calling source.ToDictionary(keySelector, null) — the 2-argument synchronous-selector overload at ToDictionary.cs:19 (e.g. source.ToDictionary(x => x.Id, null)).
Common situations: Building the selector dynamically from configuration or reflection and getting null; refactoring that removed a lambda but left the argument; conditional logic like Func<TSource,TValue> sel = cond ? x => x.Val : null.
Related errors
- Argument cannot be null (Parameter name: observer)
- Argument cannot be null (Parameter name: predicate)
- Argument cannot be null (Parameter name: predicate)
- Argument cannot be null (Parameter name: source)
- ArgumentNullException
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/9f3c5ab6f24f54dc.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToDictionary.cs:19
// 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)
throw new ArgumentNullException(nameof(comparer));
View on GitHub (pinned to 94b5d5ab91)