{"record":{"id":"9ef7ae506d86426a","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-elementselector","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'elementSelector')","messagePattern":"Value cannot be null\\. \\(Parameter 'elementSelector'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupBy.cs","lineNumber":258,"sourceCode":"            if (elementSelector == null)\n                throw new ArgumentNullException(nameof(elementSelector));\n            if (capacity < 0)\n                throw new ArgumentOutOfRangeException(nameof(capacity));\n\n            return CreateAsyncObservable<IGroupedAsyncObservable<TKey, TElement>>.From(\n                source,\n                (keySelector, elementSelector, capacity),\n                static (source, state, observer) => GroupByCore(source, observer, (o, d) => AsyncObserver.GroupBy(o, d, state.keySelector, state.elementSelector, state.capacity)));\n        }\n\n        public static IAsyncObservable<IGroupedAsyncObservable<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IAsyncObservable<TSource> source, Func<TSource, ValueTask<TKey>> keySelector, Func<TSource, ValueTask<TElement>> elementSelector, int capacity, 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 (elementSelector == null)\n                throw new ArgumentNullException(nameof(elementSelector));\n            if (capacity < 0)\n                throw new ArgumentOutOfRangeException(nameof(capacity));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n\n            return CreateAsyncObservable< IGroupedAsyncObservable<TKey, TElement>>.From(\n                source,\n                (keySelector, elementSelector, capacity, comparer),\n                static (source, state, observer) => GroupByCore(source, observer, (o, d) => AsyncObserver.GroupBy(o, d, state.keySelector, state.elementSelector, state.capacity, state.comparer)));\n        }\n\n        private static async ValueTask<IAsyncDisposable> GroupByCore<TSource, TKey, TElement>(IAsyncObservable<TSource> source, IAsyncObserver<IGroupedAsyncObservable<TKey, TElement>> observer, Func<IAsyncObserver<IGroupedAsyncObservable<TKey, TElement>>, IAsyncDisposable, (IAsyncObserver<TSource>, IAsyncDisposable)> createObserver)\n        {\n            var d = new SingleAssignmentAsyncDisposable();\n\n            var (sink, subscription) = createObserver(observer, d);\n\n            var inner = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupBy.cs#L240-L276","documentation":"AsyncRx.NET's GroupBy operator validates its arguments eagerly and throws ArgumentNullException when elementSelector is null. The elementSelector lambda maps each source element to the element exposed on each IGroupedAsyncObservable, so the library refuses to build the grouping pipeline without it. This is a fail-fast guard, not a runtime aggregation failure.","triggerScenarios":"Calling any GroupBy overload that accepts an elementSelector (e.g. AsyncObservable.GroupBy(source, keySelector, elementSelector), with capacity, or with comparer) and passing null for elementSelector.","commonSituations":"Developers call a GroupBy overload they believe takes only a keySelector but accidentally supply an extra null argument; conditional lambda construction returns null; refactoring moves the element projection out and passes a nullable delegate field that was never assigned.","solutions":["Pass a non-null element selector lambda, e.g. x => x, when the element is the source item itself.","Check which GroupBy overload you intend; if no projection is needed use the overload without elementSelector instead of passing null.","Add a null check or require!-style guard on the selector before calling GroupBy."],"exampleFix":"// before\nvar grouped = source.GroupBy(x => x.Key, (Func<Item, Item>)null);\n// after\nvar grouped = source.GroupBy(x => x.Key, x => x);","handlingStrategy":"validation","validationCode":"if (source == null) throw new ArgumentNullException(nameof(source));\nif (keySelector == null) throw new ArgumentNullException(nameof(keySelector));\nif (elementSelector == null) throw new ArgumentNullException(nameof(elementSelector));\nvar grouped = source.GroupBy(keySelector, elementSelector);","typeGuard":"bool IsValid<T, TKey, TElem>(Func<T, TKey> k, Func<T, TElem> e) => k != null && e != null;","tryCatchPattern":"try\n{\n    var grouped = source.GroupBy(keySelector, elementSelector);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"elementSelector\")\n{\n    grouped = source.GroupBy(keySelector, x => x); // identity projection fallback\n}","preventionTips":["Use the overload without elementSelector when no projection is needed instead of passing null.","Keep selectors as non-nullable Func<,> fields initialized at construction.","Enable C# nullable reference types so nullable delegates are flagged at compile time."],"tags":["argument-null","linq","groupby","asyncrx"],"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"}