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

  1. Pass a non-null value selector lambda, e.g. source.ToDictionary(x => x.Key, x => x.Value).
  2. If the selector is optional, supply a default such as x => x before calling.
  3. 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

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


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)