dotnet/reactive · error · ArgumentNullException

ArgumentNullException(nameof(other))

Error message

ArgumentNullException(nameof(other))

What it means

System.Reactive throws ArgumentNullException when the other (trigger) sequence passed to SkipUntil(source, other) is null. The source has already been validated at this point; the trigger sequence is a required argument because SkipUntil's gating behavior depends on it, so a null value throws synchronously at the call site.

Solutions

  1. Supply a real trigger sequence, e.g. a Subject<object> or Observable.Never<object>() if it should never fire
  2. Fix the provider/resolver that returned the null trigger
  3. If 'never skip' is intended, pass Observable.Empty<object>() (which fires immediately) rather than null

Example fix

// before
var gated = data.SkipUntil(trigger); // trigger == null
// after
var gated = data.SkipUntil(trigger ?? Observable.Never<Unit>());
Defensive patterns

Strategy: validation

Validate before calling

if (other is null) other = Observable.Never<Unit>(); // never fires, or Observable.Empty<Unit>() to fire immediately
var gated = source.SkipUntil(other);

Type guard

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

Try / catch

try
{
    gated = source.SkipUntil(other);
}
catch (ArgumentNullException ex) when (ex.ParamName == "other")
{
    gated = source; // skip gating entirely
}

Prevention

When it happens

Trigger: source.SkipUntil(null), e.g. a gate/trigger observable obtained from an event bus or configuration that returned null, or a field holding the trigger never initialized.

Common situations: Missing trigger wiring in composition-root code; a service returning null for the gating stream; tests where the trigger subject was not created before the pipeline was built.

Related errors


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

Appendix: source

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

        /// 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 
        /// previous inner observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
        /// <param name="sources">Observable sequence of inner observable sequences.</param>
        /// <returns>The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received.</returns>

View on GitHub (pinned to 94b5d5ab91)