{"record":{"id":"bf3f7721067121da","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-source-groupbyuntil","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'source')","messagePattern":"Value cannot be null\\. \\(Parameter 'source'\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs","lineNumber":23,"sourceCode":"using System.Collections.Concurrent;\nusing System.Collections.Generic;\nusing System.Reactive.Disposables;\nusing System.Reactive.Subjects;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<IGroupedAsyncObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector)\n        {\n            if (source == null)\n                throw new ArgumentNullException(nameof(source));\n            if (keySelector == null)\n                throw new ArgumentNullException(nameof(keySelector));\n            if (durationSelector == null)\n                throw new ArgumentNullException(nameof(durationSelector));\n\n            return CreateAsyncObservable<IGroupedAsyncObservable<TKey, TSource>>.From(\n                source,\n                (keySelector, durationSelector),\n                static (source, state, observer) => GroupByUntilCore<TSource, TKey, TSource, TDuration>(source, observer, (o, d) => AsyncObserver.GroupByUntil(o, d, state.keySelector, state.durationSelector)));\n        }\n\n        public static IAsyncObservable<IGroupedAsyncObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, 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 (durationSelector == null)\n                throw new ArgumentNullException(nameof(durationSelector));\n            if (comparer == null)\n                throw new ArgumentNullException(nameof(comparer));\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs#L5-L41","documentation":"The 2-argument GroupByUntil overload throws ArgumentNullException with the full framework message 'Value cannot be null. (Parameter 'source')' for a null source. Functionally identical to the parameter-name-only variant; the difference is only message formatting (this line is where the throw site is reported).","triggerScenarios":"Same as the base case: invoking source.GroupByUntil(keySelector, durationSelector) with a null IAsyncObservable<TSource>; the throw site lands on line 23 of GroupByUntil.cs depending on runtime inlining/JIT.","commonSituations":"Pipeline builders whose earlier stage returned null; unit tests deliberately passing null to check guard behavior; deserialized pipeline definitions where the source reference failed to resolve.","solutions":["Construct or obtain the source observable before calling GroupByUntil.","Check for null earlier in the pipeline and fail with a descriptive error.","In tests, assert that null sources produce ArgumentNullException if that is the contract."],"exampleFix":"// before\nvar grouped = maybeSource?.GroupByUntil(k, d); // maybeSource null -> throws\n// after\nif (maybeSource == null) throw new InvalidOperationException(\"source not configured\");\nvar grouped = maybeSource.GroupByUntil(k, d);","handlingStrategy":"validation","validationCode":"if (source is null) throw new ArgumentNullException(nameof(source));","typeGuard":"bool HasSource<T>(IAsyncObservable<T>? s) => s is not null;","tryCatchPattern":"try { var grouped = source.GroupByUntil(k, d); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"source\") { /* resolve source before subscribing */ }","preventionTips":["Assert source non-null before operator composition.","Avoid chaining on results of methods that can return null.","Log pipeline construction so null sources are caught near creation."],"tags":["asyncrx","null-argument","groupbyuntil","source"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}