{"record":{"id":"bdedc4d43f3cf76f","repo":"dotnet/reactive","slug":"observer-groupby","errorCode":null,"errorMessage":"observer","messagePattern":"observer","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupBy.cs","lineNumber":408,"sourceCode":"                throw new ArgumentNullException(nameof(observer));\n            if (subscription == null)\n                throw new ArgumentNullException(nameof(subscription));\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 GroupBy<TSource, TKey, TElement>(observer, subscription, x => new ValueTask<TKey>(keySelector(x)), x => new ValueTask<TElement>(elementSelector(x)), capacity, comparer);\n        }\n\n        public static (IAsyncObserver<TSource>, IAsyncDisposable) GroupBy<TSource, TKey>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, ValueTask<TKey>> keySelector)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n            if (subscription == null)\n                throw new ArgumentNullException(nameof(subscription));\n            if (keySelector == null)\n                throw new ArgumentNullException(nameof(keySelector));\n\n            return GroupBy(observer, subscription, keySelector, int.MaxValue, EqualityComparer<TKey>.Default);\n        }\n\n        public static (IAsyncObserver<TSource>, IAsyncDisposable) GroupBy<TSource, TKey>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, ValueTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)\n        {\n            if (observer == null)\n                throw new ArgumentNullException(nameof(observer));\n            if (subscription == null)\n                throw new ArgumentNullException(nameof(subscription));\n            if (keySelector == null)\n                throw new ArgumentNullException(nameof(keySelector));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupBy.cs#L390-L426","documentation":"GroupBy throws ArgumentNullException because the required observer (downstream IAsyncObserver<IGroupedAsyncObservable<TKey,TSource>>) is null. The operator validates its core arguments eagerly so an invalid subscription fails immediately rather than when events flow. It is part of the standard null-guard pattern in AsyncRx.NET operator entry points.","triggerScenarios":"Calling the 2-type-parameter GroupBy<TSource,TKey>(observer, subscription, keySelector) overload with a null observer, i.e. AsyncRx.NET.Linq.Operators.GroupBy(null, subscription, keySelector) or wiring a subscription whose observer was never created.","commonSituations":"Manually building operator chains where the observer is produced by a factory that returned null; passing a field that is not yet initialized because the observable pipeline was constructed before its observer; refactorings that swap the observer/subscription argument order.","solutions":["Ensure the IAsyncObserver<IGroupedAsyncObservable<TKey,TSource>> passed to GroupBy is non-null; construct it with a factory such as AsyncObserver.Create<TSource>(...).","Check the argument order: the observer is the first parameter, the subscription the second — swapped arguments commonly make the observer null.","Verify any variable holding the observer is initialized before GroupBy is invoked (defer construction until both observer and subscription exist).","If the observer comes from another operator, confirm that operator's return value is not null on the code path taken."],"exampleFix":"// before\nvar grp = GroupBy<TSource, TKey>(observer, subscription, x => x.Key); // observer is null\n// after\nvar obs = AsyncObserver.Create<TSource>(onNextAsync: x => default(ValueTask));\nvar grp = GroupBy<TSource, TKey>(obs, subscription, x => x.Key);","handlingStrategy":"validation","validationCode":"if (observer == null) throw new InvalidOperationException(\"observer must be provided before GroupBy\");\nvar grp = GroupBy<TSource, TKey>(observer, subscription, keySelector);","typeGuard":"bool IsValidGroupByArgs<TSource, TKey>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> o) => o is not null;","tryCatchPattern":"try { var grp = GroupBy<TSource, TKey>(observer, subscription, keySelector); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"observer\") { /* fix pipeline wiring / log */ }","preventionTips":["Always construct the observer (e.g. via AsyncObserver.Create) immediately before calling GroupBy.","Keep the (observer, subscription) parameter order in mind when upgrading between overloads.","Enable nullable reference types (<Nullable>enable</Nullable>) so null observer variables are flagged at compile time."],"tags":["argument-null","reactive-extensions","groupby","csharp"],"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"}