{"record":{"id":"ea87146ab94b605f","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-keyselector-todictionary","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'keySelector')","messagePattern":"Value cannot be null\\. \\(Parameter 'keySelector'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToDictionary.cs","lineNumber":17,"sourceCode":"﻿// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT License.\n// See the LICENSE file in the project root for more information. \n\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<IDictionary<TKey, TValue>> ToDictionary<TSource, TKey, TValue>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> valueSelector)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (keySelector == null)\n                throw new ArgumentNullException(nameof(keySelector));\n            if (valueSelector == null)\n                throw new ArgumentNullException(nameof(valueSelector));\n\n            return CreateAsyncObservable<IDictionary<TKey, TValue>>.From(\n                source,\n                (keySelector, valueSelector),\n                static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToDictionary(observer, state.keySelector, state.valueSelector)));\n        }\n\n        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)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (keySelector == null)\n                throw new ArgumentNullException(nameof(keySelector));\n            if (valueSelector == null)\n                throw new ArgumentNullException(nameof(valueSelector));\n            if (comparer == null)","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToDictionary.cs#L1-L35","documentation":"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.","triggerScenarios":"Calling source.ToDictionary(null, valueSelector); passing a selector field that was never assigned.","commonSituations":"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.","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."],"exampleFix":"// before\nFunc<Order, int> keySel = null;\nvar dict = orders.ToDictionary(keySel, o => o.Total);\n// after\nvar dict = orders.ToDictionary(o => o.Id, o => o.Total);","handlingStrategy":"validation","validationCode":"if (keySelector is null) throw new ArgumentException(\"keySelector required\");\nvar dict = source.ToDictionary(keySelector, valueSelector);","typeGuard":"static bool HasKeySelector<T, K>(Func<T, K> k) => k is not null;","tryCatchPattern":"try { var d = source.ToDictionary(ks, vs); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"keySelector\") { /* supply selector */ }","preventionTips":["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"],"tags":["csharp","async-rx","argument-null","selector"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}