{"record":{"id":"64d0bd056c440763","repo":"dotnet/reactive","slug":"argumentnullexception-nameof-valueselector","errorCode":null,"errorMessage":"ArgumentNullException(nameof(valueSelector))","messagePattern":"ArgumentNullException\\(nameof\\(valueSelector\\)\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToLookup.cs","lineNumber":20,"sourceCode":"// 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.Linq;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<ILookup<TKey, TValue>> ToLookup<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<ILookup<TKey, TValue>>.From(\n                source,\n                (keySelector, valueSelector),\n                static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToLookup(observer, state.keySelector, state.valueSelector)));\n        }\n\n        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)\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)\n                throw new ArgumentNullException(nameof(comparer));\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToLookup.cs#L2-L38","documentation":"ToLookup uses valueSelector to project each element into the value stored under its lookup key. Passing null throws ArgumentNullException(Parameter 'valueSelector') synchronously at the call site. The library checks source, keySelector, and valueSelector in order, so this guard fires only when the first two are valid.","triggerScenarios":"Calling ToLookup(source, keySelector, null) — the value-projection delegate is null while source and keySelector are valid.","commonSituations":"Query builders that assemble selectors from user input/configuration where the value mapping was omitted; copy-paste refactorings that dropped the value lambda.","solutions":["Pass an explicit value projection, e.g. x => x.Value or x => x itself.","Validate dynamically resolved selectors before calling ToLookup.","If identity projection was intended, use the source element directly (x => x)."],"exampleFix":"// before\nvar lookup = source.ToLookup(x => x.Key, valueSelector); // valueSelector null\n// after\nvar lookup = source.ToLookup(x => x.Key, x => x.Val);","handlingStrategy":"validation","validationCode":"if (valueSelector == null) throw new ArgumentException(\"valueSelector must be provided\", nameof(valueSelector));","typeGuard":"bool IsValidValueSelector<T,TValue>(Func<T,TValue> f) => f is not null;","tryCatchPattern":"try { var lookup = await source.ToLookup(keySelector, valueSelector); } catch (ArgumentNullException ex) when (ex.ParamName == \"valueSelector\") { /* supply identity or default projection */ }","preventionTips":["Default value selectors to x => x when identity projection is intended","Validate all delegate arguments once at the pipeline-construction boundary","Avoid passing through nullable delegate fields from configuration"],"tags":["null-argument","asyncrx","valueselector"],"backgroundTag":"missing-required-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}