dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'ninth')

Error message

Value cannot be null. (Parameter 'ninth')

What it means

The 9-ary Observable.Zip extension throws ArgumentNullException when any source sequence argument is null; 'ninth' identifies the ninth (last) observable as the null one. This eager guard exists so null inputs fail synchronously at the call instead of leaking into the query when subscribed.

Solutions

  1. Pass a non-null observable for the ninth argument; use Observable.Empty<T>() for an intentionally empty source.
  2. Fix the upstream producer that returned null for the ninth sequence.
  3. Guard the call site: assert all nine arguments non-null before invoking Zip.

Example fix

// before
var zipped = Observable.Zip(a, b, c, d, e, f, g, h, maybeNinth); // maybeNinth == null
// after
var ninth = maybeNinth ?? Observable.Empty<TNinth>();
var zipped = Observable.Zip(a, b, c, d, e, f, g, h, ninth);
Defensive patterns

Strategy: validation

Validate before calling

if (ninth == null)
    throw new InvalidOperationException("Zip: ninth source must be non-null; substitute Observable.Empty<TNinth>().");

Type guard

static IObservable<T> OrEmpty<T>(IObservable<T>? source) => source ?? Observable.Empty<T>();

Try / catch

try { var zipped = Observable.Zip(a, b, c, d, e, f, g, h, i); }
catch (ArgumentNullException ex) when (ex.ParamName == "ninth") { /* supply Observable.Empty<TNinth>() and retry */ }

Prevention

When it happens

Trigger: Calling Zip(first..ninth) in Observable.Multiple.Zip.cs with ninth == null, e.g. Zip(a, b, c, d, e, f, g, h, null).

Common situations: The final source in a long argument list is often supplied by the most recently added code, so it is a frequent refactoring victim; also occurs when a nullable return (FirstOrDefault, TryGet-style) is passed directly as the last argument.

Related errors


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

Appendix: source

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

        {
            if (first == null)
                throw new ArgumentNullException(nameof(first));
            if (second == null)
                throw new ArgumentNullException(nameof(second));
            if (third == null)
                throw new ArgumentNullException(nameof(third));
            if (fourth == null)
                throw new ArgumentNullException(nameof(fourth));
            if (fifth == null)
                throw new ArgumentNullException(nameof(fifth));
            if (sixth == null)
                throw new ArgumentNullException(nameof(sixth));
            if (seventh == null)
                throw new ArgumentNullException(nameof(seventh));
            if (eighth == null)
                throw new ArgumentNullException(nameof(eighth));
            if (ninth == null)
                throw new ArgumentNullException(nameof(ninth));

            return s_impl.Zip(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth);
        }

        /// <summary>
        /// Merges the specified observable sequences into one observable sequence of tuple values whenever all of the observable sequences have produced an element at a corresponding index.
        /// </summary>
        /// <typeparam name="TFirst">The type of the elements in the first source sequence.</typeparam>
        /// <typeparam name="TSecond">The type of the elements in the second source sequence.</typeparam>
        /// <typeparam name="TThird">The type of the elements in the third source sequence.</typeparam>
        /// <typeparam name="TFourth">The type of the elements in the fourth source sequence.</typeparam>
        /// <typeparam name="TFifth">The type of the elements in the fifth source sequence.</typeparam>
        /// <typeparam name="TSixth">The type of the elements in the sixth source sequence.</typeparam>
        /// <typeparam name="TSeventh">The type of the elements in the seventh source sequence.</typeparam>
        /// <typeparam name="TEighth">The type of the elements in the eighth source sequence.</typeparam>
        /// <typeparam name="TNinth">The type of the elements in the ninth source sequence.</typeparam>
        /// <typeparam name="TTenth">The type of the elements in the tenth source sequence.</typeparam>
        /// <param name="first">First observable source.</param>

View on GitHub (pinned to 94b5d5ab91)