{"record":{"id":"bf37f883f6ac4a92","repo":"dotnet/reactive","slug":"argumentnullexception-subscription","errorCode":null,"errorMessage":"ArgumentNullException: subscription","messagePattern":"ArgumentNullException: subscription","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs","lineNumber":354,"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, 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, 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":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs#L336-L372","documentation":"Thrown when the subscription IAsyncDisposable is null in the capacity overload of GroupByUntil. The subscription disposable links the grouping operator to the outer subscription lifetime and must be provided. The guard fires synchronously with the parameter name 'subscription'.","triggerScenarios":"Calling GroupByUntil(observer, null, keySelector, durationSelector, capacity) when composing operators manually outside the AsyncObservable.Run pipeline.","commonSituations":"Custom operator scaffolding that never created the disposable; test rigs constructing core overloads by hand.","solutions":["Forward the subscription disposable from your composition context","Use a no-op stub disposable in tests instead of null","Use the high-level extension overloads which obtain the subscription automatically"],"exampleFix":"// before\nreturn GroupByUntil(observer, null, ks, ds, 16);\n// after\nreturn GroupByUntil(observer, subscription, ks, ds, 16);","handlingStrategy":"validation","validationCode":"if (subscription == null) throw new ArgumentNullException(nameof(subscription));","typeGuard":"bool HasSubscription(IAsyncDisposable d) => d is not null;","tryCatchPattern":"try\n{\n    var result = await GroupByUntil(observer, subscription, ks, ds, capacity);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"subscription\")\n{\n    // wire the subscription disposable\n}","preventionTips":["Always propagate the subscription disposable from the composition root","Use stub disposables in unit tests, never null","Prefer extension overloads that obtain subscriptions automatically"],"tags":["argument-null","linq-operator","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"}