dotnet/reactive · error · ArgumentNullException

source

Error message

source

What it means

Then(source, selector) creates a QueryablePlan from a pattern source and an expression-tree selector; both must be non-null. The method throws ArgumentNullException("source") when the IQbservable<TSource> is null. The check runs before the Expression.Call for the Then operator is constructed, since a null source cannot appear in a valid queryable expression.

Solutions

  1. Ensure the source pattern comes from a valid IQbservableProvider chain ending in And/Then.
  2. Substitute an empty queryable sequence if the source legitimately has no data.
  3. Null-check the source before calling Then.

Example fix

// before
var plan = source.Then(x => x * 2); // source == null
// after
var plan = (source ?? provider.CreateQuery<int>(Observable.Empty<int>())).Then(x => x * 2);
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new InvalidOperationException("Then requires a non-null IQbservable source");
var plan = source.Then(selector);

Type guard

bool HasPatternSource<TS>(IQbservable<TS>? s) => s is not null;

Try / catch

try { var plan = source.Then(proj); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { /* rebuild the pattern source from the provider */ }

Prevention

When it happens

Trigger: Calling source.Then(selector) on a null IQbservable<TSource>, typically a pattern stage produced by a provider method that returned null.

Common situations: Building When/Then join plans where an earlier And/chain step yielded null instead of a queryable sequence.

Related errors


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

Appendix: source

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

                    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>
        /// <param name="selector">Selector that will be invoked for elements in the source sequence.</param>
        /// <returns>Plan that produces the projected results, to be fed (with other plans) to the When operator.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
        public static QueryablePlan<TResult> Then<TSource, TResult>(this IQbservable<TSource> source, Expression<Func<TSource, TResult>> selector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

            return new QueryablePlan<TResult>(
                Expression.Call(
                    null,
                    new Func<IQbservable<TSource>, Expression<Func<TSource, TResult>>, QueryablePlan<TResult>>(Then).Method,
                    source.Expression,
                    selector
                )
            );
        }

        /// <summary>

View on GitHub (pinned to 94b5d5ab91)