dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source14')

Error message

Value cannot be null. (Parameter 'source14')

What it means

This error is thrown by the generated 14-source Zip overload when the 15th source observable (source14) is null. Generated Zip operators validate each of the 14 IAsyncObservable arguments and the selector up front with ArgumentNullException so misconfiguration surfaces at call time, not at subscription time.

Solutions

  1. Verify the final source argument in the Zip call is a constructed, non-null IAsyncObservable
  2. Replace a possibly-null last source with AsyncObservable.Empty<T>() so the zip completes without values instead of throwing
  3. Assert all inputs before the call (e.g. a foreach null check or Debug.Assert) to fail fast with a clearer message
  4. Turn on nullable reference types so the compiler warns about the null argument

Example fix

// before
var zipped = src1.Zip(src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, maybeNullSrc, selector);
// after
var last = maybeNullSrc ?? AsyncObservable.Empty<T14>();
var zipped = src1.Zip(src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, last, selector);
Defensive patterns

Strategy: validation

Validate before calling

if (source14 == null) throw new ArgumentException("The last source passed to Zip must not be null.");

Type guard

static bool IsValidSource<T>(IAsyncObservable<T> source) => source is not null;

Try / catch

try
{
    var zipped = s1.Zip(s2, ..., s14, selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source14")
{
    logger.LogError(ex, "Zip: last source observable was null");
}

Prevention

When it happens

Trigger: Invoking Zip with 14 source observables and a ValueTask-returning selector where the last source argument is null: Zip(s1..s14, selector) with s14 == null.

Common situations: Constructing sources from optional configurations or nullable collections where the final element is absent; passing a method-call result that returns null on failure; copy-paste errors when adding sources one by one.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Zip.Generated.cs:1535

                throw new ArgumentNullException(nameof(source5));
            if (source6 == null)
                throw new ArgumentNullException(nameof(source6));
            if (source7 == null)
                throw new ArgumentNullException(nameof(source7));
            if (source8 == null)
                throw new ArgumentNullException(nameof(source8));
            if (source9 == null)
                throw new ArgumentNullException(nameof(source9));
            if (source10 == null)
                throw new ArgumentNullException(nameof(source10));
            if (source11 == null)
                throw new ArgumentNullException(nameof(source11));
            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 (selector == null)
                throw new ArgumentNullException(nameof(selector));

            return Create<TResult>(async observer =>
            {
                var d = new CompositeAsyncDisposable();

                var (observer1, observer2, observer3, observer4, observer5, observer6, observer7, observer8, observer9, observer10, observer11, observer12, observer13, observer14) = AsyncObserver.Zip(observer, selector);

                var sub1 = source1.SubscribeSafeAsync(observer1).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub2 = source2.SubscribeSafeAsync(observer2).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub3 = source3.SubscribeSafeAsync(observer3).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub4 = source4.SubscribeSafeAsync(observer4).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub5 = source5.SubscribeSafeAsync(observer5).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub6 = source6.SubscribeSafeAsync(observer6).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub7 = source7.SubscribeSafeAsync(observer7).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub8 = source8.SubscribeSafeAsync(observer8).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();
                var sub9 = source9.SubscribeSafeAsync(observer9).AsTask().ContinueWith(disposable => d.AddAsync(disposable.Result).AsTask()).Unwrap();

View on GitHub (pinned to 94b5d5ab91)