dotnet/reactive · error · ArgumentNullException

ArgumentNullException(nameof(source))

Error message

ArgumentNullException(nameof(source))

What it means

System.Reactive throws ArgumentNullException when the source sequence passed to SkipUntil<TSource,TOther>(source, other) is null. SkipUntil discards source elements until the other sequence emits, but a null source is a contract violation, so the operator throws synchronously before creating the implementation.

Solutions

  1. Ensure the source expression yields a real observable; use Observable.Empty<TSource>() as a neutral default
  2. Fix the upstream factory/lookup that returned null
  3. Check operator chaining for a step that may return null instead of an observable

Example fix

// before
var result = primary.SkipUntil(gate); // primary == null
// after
var result = (primary ?? Observable.Empty<int>()).SkipUntil(gate);
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new InvalidOperationException("SkipUntil requires a non-null source stream");
var result = source.SkipUntil(other);

Type guard

static bool IsStream<T>(IObservable<T>? o) => o is not null;

Try / catch

try
{
    result = source.SkipUntil(other);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    result = Observable.Empty<TSource>();
}

Prevention

When it happens

Trigger: source.SkipUntil(other) invoked on a null IObservable<TSource>, e.g. (GetMainStream() ?? null).SkipUntil(trigger) or streamVar.SkipUntil(gate) where streamVar was never assigned.

Common situations: A pipeline built conditionally where the main stream step was skipped; a factory returning null for the primary stream; refactoring where an earlier Select produced null instead of an observable.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.cs:766

        #region + SkipUntil +

        /// <summary>
        /// Returns the elements from the source observable sequence only after the other observable sequence produces an element.
        /// Starting from Rx.NET 4.0, this will subscribe to <paramref name="other"/> before subscribing to <paramref name="source" />
        /// so in case <paramref name="other" /> emits an element right away, elements from <paramref name="source" /> are not missed.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TOther">The type of the elements in the other sequence that indicates the end of skip behavior.</typeparam>
        /// <param name="source">Source sequence to propagate elements for.</param>
        /// <param name="other">Observable sequence that triggers propagation of elements of the source sequence.</param>
        /// <returns>An observable sequence containing the elements of the source sequence starting from the point the other sequence triggered propagation.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="other"/> is null.</exception>
        public static IObservable<TSource> SkipUntil<TSource, TOther>(this IObservable<TSource> source, IObservable<TOther> other)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

            return s_impl.SkipUntil(source, other);
        }

        #endregion

        #region + Switch +

        /// <summary>
        /// Transforms an observable sequence of observable sequences into an observable sequence 
        /// producing values only from the most recent observable sequence.
        /// Each time a new inner observable sequence is received, unsubscribe from the 

View on GitHub (pinned to 94b5d5ab91)