dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source1')

Error message

Value cannot be null. (Parameter 'source1')

What it means

A second 7-source Zip overload (with an async selector of type Func<T1..T7, ValueTask<TResult>>) validates source1 first and throws ArgumentNullException('source1') when the first observable is null. This is eager fail-fast validation before any operator state is created.

Solutions

  1. Ensure the first argument is a constructed IAsyncObservable; check its origin for null-returning paths.
  2. Substitute AsyncObservable.Empty<T1>() when absence is a legitimate case.
  3. Add a null guard or Debug.Assert at the call boundary.

Example fix

// before
var out = AsyncObservable.Zip(head, s2, s3, s4, s5, s6, s7, selector);
// after
if (head == null) throw new InvalidOperationException("head source missing");
var out = AsyncObservable.Zip(head, s2, s3, s4, s5, s6, s7, selector);
Defensive patterns

Strategy: validation

Validate before calling

if (source1 == null) throw new InvalidOperationException("primary zip source must be non-null");

Type guard

bool IsValidZipInput<T>(IAsyncObservable<T> s) => s is not null;

Try / catch

try
{
    var zipped = AsyncObservable.Zip(s1, s2, s3, s4, s5, s6, s7, selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source1")
{
    logger.LogError(ex, "primary zip source was null");
}

Prevention

When it happens

Trigger: Calling AsyncObservable.Zip(null, source2, source3, source4, source5, source6, source7, selector) with a null first IAsyncObservable argument.

Common situations: The primary/head stream comes from a method that returned null on an error path; a chained call like GetHead()?.Zip(...) was flattened and the null propagated; generic helper methods receiving a null 'main' observable.

Related errors


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

Appendix: source

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

                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();

                await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7).ConfigureAwait(false);

                return d;
            });
        }

        public static IAsyncObservable<TResult> Zip<T1, T2, T3, T4, T5, T6, T7, TResult>(this IAsyncObservable<T1> source1, IAsyncObservable<T2> source2, IAsyncObservable<T3> source3, IAsyncObservable<T4> source4, IAsyncObservable<T5> source5, IAsyncObservable<T6> source6, IAsyncObservable<T7> source7, Func<T1, T2, T3, T4, T5, T6, T7, ValueTask<TResult>> selector)
        {
            if (source1 == null)
                throw new ArgumentNullException(nameof(source1));
            if (source2 == null)
                throw new ArgumentNullException(nameof(source2));
            if (source3 == null)
                throw new ArgumentNullException(nameof(source3));
            if (source4 == null)
                throw new ArgumentNullException(nameof(source4));
            if (source5 == null)
                throw new ArgumentNullException(nameof(source5));
            if (source6 == null)
                throw new ArgumentNullException(nameof(source6));
            if (source7 == null)
                throw new ArgumentNullException(nameof(source7));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));

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

View on GitHub (pinned to 94b5d5ab91)