{"record":{"id":"51be17d8d29d992c","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-right","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'right')","messagePattern":"Value cannot be null\\. \\(Parameter 'right'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupJoin.cs","lineNumber":20,"sourceCode":"// 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.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);","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupJoin.cs#L2-L38","documentation":"GroupJoin requires the `right` source sequence; a null right-hand observable is rejected with ArgumentNullException as the second guard in the method. Without a right sequence there is nothing to join durations against, so fail-fast is intentional.","triggerScenarios":"Calling `left.GroupJoin(null, leftDurationSelector, rightDurationSelector, resultSelector)` or passing a null-returning right-stream factory to the static AsyncObservable.GroupJoin.","commonSituations":"Right stream conditionally loaded (e.g. null when a feed is disabled); config-driven stream selection returning null; refactoring that renamed the right-source variable ahead of its assignment.","solutions":["Substitute AsyncObservable.Empty<TRight>() when the right stream is intentionally absent.","Null-check/initialize the right observable before composing the join.","Verify the factory method producing the right stream never returns null."],"exampleFix":"// before\nvar result = left.GroupJoin(maybeRight, lds, rds, rs);\n// after\nvar result = left.GroupJoin(maybeRight ?? AsyncObservable.Empty<TRight>(), lds, rds, rs);","handlingStrategy":"validation","validationCode":"if (right is null) throw new ArgumentNullException(nameof(right));\n// or normalize:\nright ??= AsyncObservable.Empty<TRight>();","typeGuard":"bool IsValidSource<T>(IAsyncObservable<T>? s) => s is not null;","tryCatchPattern":"try\n{\n    var result = left.GroupJoin(right, lds, rds, rs);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"right\")\n{\n    var result = AsyncObservable.Empty<TResult>();\n}","preventionTips":["Substitute AsyncObservable.Empty<TRight>() when the right stream is disabled by config.","Assert stream factories never return null; unit-test the disabled-stream path.","Initialize right-source fields at construction, not lazily on first use."],"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"}