{"record":{"id":"51300b4e188e102d","repo":"dotnet/reactive","slug":"left","errorCode":null,"errorMessage":"left","messagePattern":"left","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"AsyncRx.NET/System.Reactive.Async/Linq/Operators/Join.cs","lineNumber":17,"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.Generic;\nusing System.Reactive.Disposables;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace System.Reactive.Linq\n{\n    public partial class AsyncObservable\n    {\n        public static IAsyncObservable<TResult> Join<TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IAsyncObservable<TLeft> left, IAsyncObservable<TRight> right, Func<TLeft, IAsyncObservable<TLeftDuration>> leftDurationSelector, Func<TRight, IAsyncObservable<TRightDuration>> rightDurationSelector, Func<TLeft, 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 CreateAsyncObservable<TResult>.From(\n                left,\n                (right, leftDurationSelector, rightDurationSelector, resultSelector),\n                static async (left, state, observer) =>\n                {\n                    var subscriptions = new CompositeAsyncDisposable();\n\n                    var (leftObserver, rightObserver, disposable) = AsyncObserver.Join(observer, subscriptions, state.leftDurationSelector, state.rightDurationSelector, state.resultSelector);\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/AsyncRx.NET/System.Reactive.Async/Linq/Operators/Join.cs#L1-L35","documentation":"Join(left, right, leftDurationSelector, rightDurationSelector, resultSelector) throws ArgumentNullException with paramName \"left\" when the left (outer) observable is null. The operator validates all five arguments eagerly in order, so 'left' failing means the very first argument was null.","triggerScenarios":"Calling left.Join(right, ...) via a null extension receiver, or AsyncObservable.Join(null, right, ...) where the left observable came from a null-returning producer.","commonSituations":"Joining streams where one side is loaded lazily (e.g. a user/session stream that hasn't been created yet), or composing streams from services that may return null before initialization.","solutions":["Ensure the left IAsyncObservable<TLeft> is non-null; substitute AsyncObservable.Empty<TLeft>() when a side is legitimately absent.","Trace the null producer for the left stream and fix it to return an empty observable.","Guard each side with a null check (or ?? Empty) before composing the Join."],"exampleFix":"// before\nvar joined = left.Join(right, l => lDur, r => rDur, selector); // left is null\n// after\nvar joined = (left ?? AsyncObservable.Empty<Left>())\n    .Join(right, l => lDur, r => rDur, selector);","handlingStrategy":"validation","validationCode":"if (left is null) throw new ArgumentException(\"left must be non-null\", nameof(left));\n// or: left ??= AsyncObservable.Empty<TLeft>();","typeGuard":"static bool HasLeft<TLeft>(IAsyncObservable<TLeft> o) => o is not null;","tryCatchPattern":"try { var joined = left.Join(right, ld, rd, selector); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"left\") { /* ensure left stream is initialized */ }","preventionTips":["Verify both join inputs are initialized before composition","Substitute Empty<T>() for streams that may not exist yet","Eagerly create session/user streams rather than lazily returning null"],"tags":["argument-null","operators","join","reactive"],"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"}