{"record":{"id":"74defd96fef96246","repo":"dotnet/reactive","slug":"argumentnullexception-nameof-comparer-tolookup","errorCode":null,"errorMessage":"ArgumentNullException(nameof(comparer))","messagePattern":"ArgumentNullException\\(nameof\\(comparer\\)\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToLookup.cs","lineNumber":37,"sourceCode":"            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\n            return CreateAsyncObservable<ILookup<TKey, TValue>>.From(\n                source,\n                (keySelector, valueSelector, comparer),\n                static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToLookup(observer, state.keySelector, state.valueSelector, state.comparer)));\n        }\n\n        public static IAsyncObservable<ILookup<TKey, TValue>> ToLookup<TSource, TKey, TValue>(this IAsyncObservable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<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,","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/ToLookup.cs#L19-L55","documentation":"The comparer overload of ToLookup requires a non-null IEqualityComparer<TKey>. Passing a null comparer throws ArgumentNullException(nameof(comparer)) synchronously; pass EqualityComparer<TKey>.Default for default key comparison.","triggerScenarios":"Calling source.ToLookup(keySelector, valueSelector, comparer) with comparer == null, usually because a comparer field was null or the comparer parameter defaulted to null.","commonSituations":"Injecting custom comparers via DI where registration is missing; conditionally chosen comparers that end up null for a given key type.","solutions":["Use EqualityComparer<TKey>.Default when you want default comparison.","Verify your comparer is constructed/registered before building the query.","Drop the comparer argument and use the two-selector overload."],"exampleFix":"// before\nIEqualityComparer<string> cmp = GetComparer(); // may be null\nvar lookup = src.ToLookup(o => o.Name, o => o, cmp);\n// after\nvar cmp = GetComparer() ?? EqualityComparer<string>.Default;\nvar lookup = src.ToLookup(o => o.Name, o => o, cmp);","handlingStrategy":"validation","validationCode":"var cmp = maybeComparer ?? EqualityComparer<TKey>.Default;\nif (cmp is null) throw new ArgumentNullException(nameof(comparer));","typeGuard":"static bool IsValidComparer<TKey>(IEqualityComparer<TKey> c) => c is not null;","tryCatchPattern":"try { var lookup = src.ToLookup(keySel, valSel, cmp); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"comparer\") { /* fall back to default comparer */ }","preventionTips":["Default to EqualityComparer<TKey>.Default for standard key types.","Verify DI registrations provide the comparer (e.g. validate the container at startup).","Never expose nullable comparer fields in query-building classes."],"tags":["null-reference","comparer","argument-validation","linq"],"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"}