{"record":{"id":"54417c62223d8e70","repo":"dotnet/reactive","slug":"leftdurationselector","errorCode":null,"errorMessage":"leftDurationSelector","messagePattern":"leftDurationSelector","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupJoin.cs","lineNumber":22,"sourceCode":"\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<TResult> GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IAsyncObservable<TLeft> left, IAsyncObservable<TRight> right, Func<TLeft, IAsyncObservable<TLeftDuration>> leftDurationSelector, Func<TRight, IAsyncObservable<TRightDuration>> rightDurationSelector, Func<TLeft, IAsyncObservable<TRight>, TResult> resultSelector)\n        {\n            if (left == null)\n                throw new ArgumentNullException(nameof(left));\n            if (right == null)\n                throw new ArgumentNullException(nameof(right));\n            if (leftDurationSelector == null)\n                throw new ArgumentNullException(nameof(leftDurationSelector));\n            if (rightDurationSelector == null)\n                throw new ArgumentNullException(nameof(rightDurationSelector));\n            if (resultSelector == null)\n                throw new ArgumentNullException(nameof(resultSelector));\n\n            return Create<TResult>(async observer =>\n            {\n                var subscriptions = new CompositeAsyncDisposable();\n\n                var (leftObserver, rightObserver, disposable) = AsyncObserver.GroupJoin(observer, subscriptions, leftDurationSelector, rightDurationSelector, resultSelector);\n\n                var leftSubscription = await left.SubscribeSafeAsync(leftObserver).ConfigureAwait(false);\n                await subscriptions.AddAsync(leftSubscription).ConfigureAwait(false);\n\n                var rightSubscription = await right.SubscribeSafeAsync(rightObserver).ConfigureAwait(false);\n                await subscriptions.AddAsync(rightSubscription).ConfigureAwait(false);\n\n                return disposable;","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupJoin.cs#L4-L40","documentation":"GroupJoin needs leftDurationSelector to compute, for each left item, the observable whose completion ends that item's join window. A null selector makes windowing impossible, so ArgumentNullException is thrown at call time (third guard in the method).","triggerScenarios":"Calling GroupJoin with null as the `leftDurationSelector` (Func<TLeft, IAsyncObservable<TLeftDuration>>), e.g. `left.GroupJoin(right, null, rds, rs)`.","commonSituations":"Migrating from Join/SelectMany-style code that lacked duration semantics; overloads confused after adding duration selectors in a refactor; dynamic query builders that skip optional delegates.","solutions":["Provide a duration observable per left item, e.g. `l => timer` or `l => AsyncObservable.Empty<TLeftDuration>()` for windows that end on the next right event per your design.","If you don't need windowed semantics, use a different operator (e.g. Zip or CombineLatest).","Check that your lambda actually binds to leftDurationSelector (first selector slot)."],"exampleFix":"// before\nvar result = left.GroupJoin(right, null, r => r.Take(1), (l, rs) => rs);\n// after\nvar result = left.GroupJoin(right, l => leftTimer, r => r.Take(1), (l, rs) => rs);","handlingStrategy":"validation","validationCode":"if (leftDurationSelector is null) throw new ArgumentNullException(nameof(leftDurationSelector));","typeGuard":"bool IsValidSelector<TLeft,TDur>(Func<TLeft, IAsyncObservable<TDur>>? f) => f is not null;","tryCatchPattern":"try\n{\n    var result = left.GroupJoin(right, lds, rds, rs);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"leftDurationSelector\")\n{\n    // fall back to a non-windowed operator (Zip/CombineLatest)\n}","preventionTips":["Always pair GroupJoin with explicit duration observables for both sides.","Remember parameter order: leftDurationSelector comes before rightDurationSelector.","If you have no duration semantics, GroupJoin is the wrong operator."],"tags":["argparse","null-check","async-rx"],"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"}