dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'rightDurationSelector')

Error message

Value cannot be null. (Parameter 'rightDurationSelector')

What it means

GroupJoin threw ArgumentNullException because the rightDurationSelector delegate was null. This selector defines how long each right element participates in the join; the public entry point validates it synchronously before building the query.

Solutions

  1. Provide a non-null right duration selector, e.g. r => Observable.Timer(r.Ttl).
  2. Null-check the delegate before the call and surface a descriptive error.
  3. Use Observable.Empty<Unit>() for right elements with zero duration.

Example fix

// before
var joined = left.GroupJoin(right, l => l.Window(), _rightDuration, (l, rs) => ...); // _rightDuration null
// after
var joined = left.GroupJoin(right, l => l.Window(), r => Observable.Timer(r.Ttl), (l, rs) => ...);
Defensive patterns

Strategy: validation

Validate before calling

if (rightDurationSelector == null)
    rightDurationSelector = _ => Observable.Never<Unit>();

Type guard

bool HasRightDuration<TRight>(Func<TRight, IObservable<Unit>>? f) => f is not null;

Try / catch

try
{
    var joined = left.GroupJoin(right, leftDurationSelector, rightDurationSelector, resultSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "rightDurationSelector")
{
    // apply default right-window policy
}

Prevention

When it happens

Trigger: Calling left.GroupJoin(right, leftDurationSelector, null, resultSelector) — commonly a null duration lambda from a nullable field or an unconfigured parameter.

Common situations: Duration windows read from configuration that were never assigned; helper wrappers passing through optional selectors; incomplete refactors of join call sites.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/d99b268335c1460e. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs:861

        {
            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)
            {
                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>

View on GitHub (pinned to 94b5d5ab91)