{"record":{"id":"1f71fa5e61a4e687","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-left-observable","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'left')","messagePattern":"Value cannot be null\\. \\(Parameter 'left'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs","lineNumber":846,"sourceCode":"        /// Correlates the elements of two sequences based on overlapping durations, and groups the results.\n        /// </summary>\n        /// <typeparam name=\"TLeft\">The type of the elements in the left source sequence.</typeparam>\n        /// <typeparam name=\"TRight\">The type of the elements in the right source sequence.</typeparam>\n        /// <typeparam name=\"TLeftDuration\">The type of the elements in the duration sequence denoting the computed duration of each element in the left source sequence.</typeparam>\n        /// <typeparam name=\"TRightDuration\">The type of the elements in the duration sequence denoting the computed duration of each element in the right source sequence.</typeparam>\n        /// <typeparam name=\"TResult\">The type of the elements in the result sequence, obtained by invoking the result selector function for source elements with overlapping duration.</typeparam>\n        /// <param name=\"left\">The left observable sequence to join elements for.</param>\n        /// <param name=\"right\">The right observable sequence to join elements for.</param>\n        /// <param name=\"leftDurationSelector\">A function to select the duration of each element of the left observable sequence, used to determine overlap.</param>\n        /// <param name=\"rightDurationSelector\">A function to select the duration of each element of the right observable sequence, used to determine overlap.</param>\n        /// <param name=\"resultSelector\">A function invoked to compute a result element for any element of the left sequence with overlapping elements from the right observable sequence.</param>\n        /// <returns>An observable sequence that contains result elements computed from source elements that have an overlapping duration.</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"left\"/> or <paramref name=\"right\"/> or <paramref name=\"leftDurationSelector\"/> or <paramref name=\"rightDurationSelector\"/> or <paramref name=\"resultSelector\"/> is null.</exception>\n        public static IObservable<TResult> GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, IObservable<TLeftDuration>> leftDurationSelector, Func<TRight, IObservable<TRightDuration>> rightDurationSelector, Func<TLeft, IObservable<TRight>, TResult> resultSelector)\n        {\n            if (left == null)\n            {\n                throw new ArgumentNullException(nameof(left));\n            }\n\n            if (right == null)\n            {\n                throw new ArgumentNullException(nameof(right));\n            }\n\n            if (leftDurationSelector == null)\n            {\n                throw new ArgumentNullException(nameof(leftDurationSelector));\n            }\n\n            if (rightDurationSelector == null)\n            {\n                throw new ArgumentNullException(nameof(rightDurationSelector));\n            }\n\n            if (resultSelector == null)","sourceCodeStart":828,"sourceCodeEnd":864,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs#L828-L864","documentation":"GroupJoin threw ArgumentNullException because the left observable was null. The public operator validates left, right, all three selectors synchronously before constructing the query; left is the outer sequence and cannot be null.","triggerScenarios":"Calling left.GroupJoin(right, ...) where the receiver is null — e.g. a nullable IObservable from a factory or a field not yet assigned.","commonSituations":"Null results from service-located streams; optional outer streams represented as null instead of Observable.Empty; races where a stream field is read before initialization.","solutions":["Initialize the left observable before calling GroupJoin.","Coalesce to Observable.Empty<TLeft>() when the left stream is legitimately absent.","Null-check and throw a descriptive exception identifying the upstream source of the null."],"exampleFix":"// before\nvar joined = leftStream.GroupJoin(rightStream, l => l.Window(), r => r.Window(), (l, rs) => ...); // leftStream null\n// after\nvar joined = (leftStream ?? Observable.Empty<Left>()).GroupJoin(rightStream, l => l.Window(), r => r.Window(), (l, rs) => ...);","handlingStrategy":"validation","validationCode":"if (left == null)\n    left = Observable.Empty<TLeft>();","typeGuard":"bool HasLeft<T>(IObservable<T>? s) => s is not null;","tryCatchPattern":"try\n{\n    var joined = left.GroupJoin(right, ld, rd, rs);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"left\")\n{\n    // resolve or create the left stream\n}","preventionTips":["Resolve all stream sources before building joins.","Represent absent outer streams with Observable.Empty, never null.","Use nullable reference types so null observables surface at compile time."],"tags":["null-argument","linq","reactive-extensions","groupjoin"],"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"}