dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'resultSelector')
Error message
Value cannot be null. (Parameter 'resultSelector')
What it means
GroupJoin threw ArgumentNullException because the resultSelector delegate was null. The result selector combines each left element with the observable of overlapping right elements; the public operator validates it synchronously.
Solutions
- Pass a non-null result selector, e.g. (l, rights) => ... .
- Null-check the delegate before the call and fail with context.
- If projection should be identity-like, write an explicit lambda rather than null.
Example fix
// before var joined = left.GroupJoin(right, l => l.Window(), r => r.Window(), _projector); // null // after var joined = left.GroupJoin(right, l => l.Window(), r => r.Window(), (l, rights) => new Pair(l, rights));
Defensive patterns
Strategy: validation
Validate before calling
if (resultSelector == null)
throw new ArgumentException("resultSelector is required to combine joined streams.", nameof(resultSelector)); Type guard
bool HasResultSelector<TLeft,TRight,TResult>(Func<TLeft, IObservable<TRight>, TResult>? f) => f is not null;
Try / catch
try
{
var joined = left.GroupJoin(right, ld, rd, resultSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "resultSelector")
{
// supply a default projection
} Prevention
- Write result selectors inline at the call site.
- Never model 'no projection' as null; write an explicit combining lambda.
- Type projection delegate fields as non-nullable and initialize them at construction.
When it happens
Trigger: Calling left.GroupJoin(right, leftDurationSelector, rightDurationSelector, null) — e.g. a projection lambda stored in a nullable Func field or forwarded parameter.
Common situations: Dynamic query building where the projection is optional; storing lambdas in configuration; refactoring that left the result selector parameter unfilled.
Related errors
- Value cannot be null. (Parameter 'left')
- Value cannot be null. (Parameter 'leftDurationSelector')
- 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/73950ae8b3053ff5.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs:866
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)
{
throw new ArgumentNullException(nameof(resultSelector));
}
return s_impl.GroupJoin(left, right, leftDurationSelector, rightDurationSelector, resultSelector);
}
#endregion
#region + Join +
/// <summary>
/// Correlates the elements of two sequences based on overlapping durations.
/// </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>View on GitHub (pinned to 94b5d5ab91)