{"record":{"id":"ceb248608dc41255","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-subscription-groupbyuntil","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'subscription')","messagePattern":"Value cannot be null\\. \\(Parameter 'subscription'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs","lineNumber":490,"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 (durationSelector == null)\n                throw new ArgumentNullException(nameof(durationSelector));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n\n            return GroupByUntil(observer, subscription, keySelector, durationSelector, int.MaxValue, comparer);\n        }\n\n        public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, ValueTask<TKey>> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, int capacity)\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 (durationSelector == null)\n                throw new ArgumentNullException(nameof(durationSelector));\n            if (capacity < 0)\n                throw new ArgumentOutOfRangeException(nameof(capacity));\n\n            return GroupByUntil(observer, subscription, keySelector, durationSelector, capacity, EqualityComparer<TKey>.Default);\n        }\n\n        public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, ValueTask<TKey>> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, int capacity, 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));","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs#L472-L508","documentation":"The capacity-based GroupByUntil overload requires an IAsyncDisposable subscription used to tie the operator's lifetime to the outer subscription. It throws ArgumentNullException when subscription is null.","triggerScenarios":"Calling GroupByUntil(observer, subscription, keySelector, durationSelector, capacity) with a null IAsyncDisposable subscription argument.","commonSituations":"Directly invoking internal operator entry points from custom query composition or tests without creating a subscription disposable first.","solutions":["Pass the subscription disposable supplied by the enclosing query composition (e.g. from Create/Subscribe plumbing).","Create a disposable (e.g. AsyncDisposable or a composite of upstream disposables) to represent the subscription.","Guard with a null check and skip calling the operator when no subscription exists."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (subscription == null) throw new InvalidOperationException(\"GroupByUntil requires a subscription disposable\");","typeGuard":"static bool HasSubscription(IAsyncDisposable d) => d is not null;","tryCatchPattern":"try { await GroupByUntil(observer, subscription, keySel, durSel, capacity); } catch (ArgumentNullException ex) when (ex.ParamName == \"subscription\") { /* create a disposable and retry */ }","preventionTips":["Thread the subscription disposable through your operator compositions consistently.","Use a composite disposable when combining multiple upstream resources.","Add unit tests for manual operator composition plumbing."],"tags":["null-argument","argument-validation","reactive-extensions"],"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"}