dotnet/reactive · error · ArgumentNullException

source15

Error message

source15

What it means

This ArgumentNullException is thrown synchronously by the public Zip extension method when the fifteenth source observable (source15) is null. Rx operators validate all arguments up front before subscribing, so a null source is rejected immediately rather than surfacing later as a NullReferenceException inside the query. The 15-source overload requires every input sequence to be a non-null IObservable<T>.

Solutions

  1. Ensure source15 is assigned a valid IObservable<TSource15> instance before calling Zip
  2. If 'no data' is intended, pass Observable.Empty<TSource15>() instead of null
  3. Guard the call site with a null check and throw a meaningful application-level error or use a default source
  4. If sources come from a collection, filter or validate entries with a null check before zipping

Example fix

// before
var zipped = Observable.Zip(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, null, (a, b) => a + b);
// after
IObservable<int> s15 = GetFifteenthSource() ?? Observable.Empty<int>();
var zipped = Observable.Zip(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, (a, b) => a + b);
Defensive patterns

Strategy: validation

Validate before calling

if (source15 == null)
{
    source15 = Observable.Empty<TSource15>(); // or throw a domain-specific error
}
var zipped = Observable.Zip(s1, ..., source15, resultSelector);

Type guard

static bool IsValidSource<TSource15>(IObservable<TSource15> s) => s is not null;

Try / catch

try
{
    var zipped = Observable.Zip(s1, ..., s15, selector);
    return zipped;
}
catch (ArgumentNullException ex) when (ex.ParamName == nameof(source15))
{
    // log which source was null and fall back to an empty/alternate pipeline
    return Observable.Empty<TResult>();
}

Prevention

When it happens

Trigger: Calling Observable.Zip(source1..source14, null, resultSelector) - i.e. the 15-argument overload of Zip with source15 passed as null while all other arguments are non-null. The check executes synchronously at the Zip call site (Observable.Multiple.Zip.cs:1040).

Common situations: Building zip chains programmatically where one entry in a source array/collection is null; refactoring from a 14-source Zip to 15 sources and forgetting to wire the new source; a factory or DI method returning null instead of an empty observable; LINQ query syntax where an intermediate expression evaluates to null.

Related errors


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

Appendix: source

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

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

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

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

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

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

            return s_impl.Zip(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, source14, source15, resultSelector);
        }

        /// <summary>
        /// Merges the specified observable sequences into one observable sequence by using the selector function whenever all of the observable sequences have produced an element at a corresponding index.
        /// </summary>
        /// <typeparam name="TSource1">The type of the elements in the first source sequence.</typeparam>
        /// <typeparam name="TSource2">The type of the elements in the second source sequence.</typeparam>
        /// <typeparam name="TSource3">The type of the elements in the third source sequence.</typeparam>
        /// <typeparam name="TSource4">The type of the elements in the fourth source sequence.</typeparam>
        /// <typeparam name="TSource5">The type of the elements in the fifth source sequence.</typeparam>

View on GitHub (pinned to 94b5d5ab91)