dotnet/reactive · error · ArgumentNullException

right

Error message

right

What it means

And(left, right) requires the right-hand IObservable<TRight> to be non-null; the method throws ArgumentNullException("right") before building the Expression.Call that embeds the And call into the queryable expression tree. The right sequence is a plain IObservable operand of the pattern, and a null reference cannot be represented in the expression.

Solutions

  1. Pass a valid IObservable<TRight>, e.g. Observable.Empty<TRight>() as a safe placeholder.
  2. Initialize/await the right-hand stream before composing the And pattern.
  3. Guard with a null check and skip pattern construction if the right stream is unavailable.

Example fix

// before
var pattern = left.And(rightStream); // rightStream == null
// after
var pattern = left.And(rightStream ?? Observable.Empty<TRight>());
Defensive patterns

Strategy: validation

Validate before calling

if (right is null) right = Observable.Empty<TRight>();
var pattern = left.And(right);

Type guard

bool HasRightStream<TR>(IObservable<TR>? r) => r is not null;

Try / catch

try { var pattern = left.And(right); }
catch (ArgumentNullException ex) when (ex.ParamName == "right") { var pattern = left.And(Observable.Empty<TRight>()); }

Prevention

When it happens

Trigger: Calling left.And(null) or passing a right-hand observable variable that is null, commonly obtained from a failed lookup or uninitialized field.

Common situations: Composing patterns where the second stream comes from another service or event hookup that has not been initialized yet.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Qbservable.Joins.cs:34

        /// <summary>
        /// Creates a pattern that matches when both observable sequences have an available element.
        /// </summary>
        /// <typeparam name="TLeft">The type of the elements in the left sequence.</typeparam>
        /// <typeparam name="TRight">The type of the elements in the right sequence.</typeparam>
        /// <param name="left">Observable sequence to match with the right sequence.</param>
        /// <param name="right">Observable sequence to match with the left sequence.</param>
        /// <returns>Pattern object that matches when both observable sequences have an available element.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="left"/> or <paramref name="right"/> is null.</exception>
        public static QueryablePattern<TLeft, TRight> And<TLeft, TRight>(this IQbservable<TLeft> left, IObservable<TRight> right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }

            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            return new QueryablePattern<TLeft, TRight>(
                Expression.Call(
                    null,
                    new Func<IQbservable<TLeft>, IObservable<TRight>, QueryablePattern<TLeft, TRight>>(And).Method,
                    left.Expression,
                    GetSourceExpression(right)
                )
            );
        }

        /// <summary>
        /// Matches when the observable sequence has an available element and projects the element by invoking the selector function.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence, returned by the selector function.</typeparam>
        /// <param name="source">Observable sequence to apply the selector on.</param>

View on GitHub (pinned to 94b5d5ab91)