dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'left')
Error message
Value cannot be null. (Parameter 'left')
What it means
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.
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.
Example fix
// before var joined = leftStream.GroupJoin(rightStream, l => l.Window(), r => r.Window(), (l, rs) => ...); // leftStream null // after var joined = (leftStream ?? Observable.Empty<Left>()).GroupJoin(rightStream, l => l.Window(), r => r.Window(), (l, rs) => ...);
Defensive patterns
Strategy: validation
Validate before calling
if (left == null)
left = Observable.Empty<TLeft>(); Type guard
bool HasLeft<T>(IObservable<T>? s) => s is not null;
Try / catch
try
{
var joined = left.GroupJoin(right, ld, rd, rs);
}
catch (ArgumentNullException ex) when (ex.ParamName == "left")
{
// resolve or create the left stream
} Prevention
- 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.
When it happens
Trigger: Calling left.GroupJoin(right, ...) where the receiver is null — e.g. a nullable IObservable from a factory or a field not yet assigned.
Common situations: 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.
Related errors
- Value cannot be null. (Parameter 'leftDurationSelector')
- Value cannot be null. (Parameter 'resultSelector')
- Value cannot be null. (Parameter 'right')
- Value cannot be null. (Parameter 'rightDurationSelector')
- Value cannot be null. (Parameter 'onCompleted')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/1f71fa5e61a4e687.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs:846
/// Correlates the elements of two sequences based on overlapping durations, and groups the results.
/// </summary>
/// <typeparam name="TLeft">The type of the elements in the left source sequence.</typeparam>
/// <typeparam name="TRight">The type of the elements in the right source sequence.</typeparam>
/// <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>
/// <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>
/// <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>
/// <param name="left">The left observable sequence to join elements for.</param>
/// <param name="right">The right observable sequence to join elements for.</param>
/// <param name="leftDurationSelector">A function to select the duration of each element of the left observable sequence, used to determine overlap.</param>
/// <param name="rightDurationSelector">A function to select the duration of each element of the right observable sequence, used to determine overlap.</param>
/// <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>
/// <returns>An observable sequence that contains result elements computed from source elements that have an overlapping duration.</returns>
/// <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>
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)
{
if (left == null)
{
throw new ArgumentNullException(nameof(left));
}
if (right == null)
{
throw new ArgumentNullException(nameof(right));
}
if (leftDurationSelector == null)
{
throw new ArgumentNullException(nameof(leftDurationSelector));
}
if (rightDurationSelector == null)
{
throw new ArgumentNullException(nameof(rightDurationSelector));
}
if (resultSelector == null)View on GitHub (pinned to 94b5d5ab91)