{"record":{"id":"893146ed9adc20a9","repo":"dotnet/reactive","slug":"source-groupbyuntil","errorCode":null,"errorMessage":"source","messagePattern":"source","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs","lineNumber":19,"sourceCode":"﻿// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT License.\n// See the LICENSE file in the project root for more information. \n\nusing 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)","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs#L1-L37","documentation":"AsyncObservable.GroupByUntil (the 2-argument overload) throws ArgumentNullException when the source observable is null. GroupByUntil groups elements by key and closes each group when the duration observable fires; without a source there is nothing to subscribe to. All guards run synchronously at call time, before CreateAsyncObservable is invoked.","triggerScenarios":"Calling source.GroupByUntil(keySelector, durationSelector) where the source variable is null, typically an uninitialized IAsyncObservable<TSource> or the null result of a failed factory chain.","commonSituations":"Chaining operators where an earlier factory returned null; conditional observable construction skipped in a branch; fields not yet assigned when a subscription path runs early.","solutions":["Ensure the source is created (e.g. via CreateAsyncObservable or another operator) before calling GroupByUntil.","Add a null check on the source earlier in your composition code to get a clearer stack trace.","Guard conditional pipelines so GroupByUntil is only invoked with a valid source."],"exampleFix":"// before\nIAsyncObservable<Event> source = null;\nvar grouped = source.GroupByUntil(e => e.Key, g => g.Take(1));\n// after\nvar source = CreateAsyncObservable<Event>.From(...);\nvar grouped = source.GroupByUntil(e => e.Key, g => g.Take(1));","handlingStrategy":"validation","validationCode":"if (source is null) throw new ArgumentNullException(nameof(source));\nif (keySelector is null) throw new ArgumentNullException(nameof(keySelector));\nif (durationSelector is null) throw new ArgumentNullException(nameof(durationSelector));","typeGuard":"bool CanGroupByUntil<T,TKey>(IAsyncObservable<T>? s, Func<T,TKey>? k) => s is not null && k is not null;","tryCatchPattern":"try { var grouped = source.GroupByUntil(k, d); }\ncatch (ArgumentNullException ex) { /* ex.ParamName tells which argument was null */ }","preventionTips":["Check that each pipeline stage returns a non-null observable.","Enable nullable reference types to catch uninitialized sources.","Fail fast in composition code when a source factory yields null."],"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"}