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
- Verify the final source argument in the Zip call is a constructed, non-null IAsyncObservable
- Replace a possibly-null last source with AsyncObservable.Empty<T>() so the zip completes without values instead of throwing
- Assert all inputs before the call (e.g. a foreach null check or Debug.Assert) to fail fast with a clearer message
- 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
- Verify all 14 arguments in the call, especially the last one, before invoking Zip
- Default optional sources to AsyncObservable.Empty<T>() instead of null
- Enable nullable reference types to catch the null at compile time
- Wrap long Zip calls in a helper that validates the source array first
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
- Value cannot be null. (Parameter 'source13')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'error')
- ArgumentNullException
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)