dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'resultSelector')

Error message

Value cannot be null. (Parameter 'resultSelector')

What it means

Wait—this index refers to the four-source Zip overload's source1 check, but the error message says source1 at Observable.Multiple.Zip.cs:68. The four-source Observable.Zip overload throws ArgumentNullException when source1 is null. As with other Rx combinators, arguments are validated eagerly at the public boundary. Supply a non-null first IObservable.

Solutions

  1. Ensure the first observable is non-null before calling the four-source Zip.
  2. Use Observable.Empty<TSource1>() as a fallback for an optional first source.
  3. Run a null check across all sources and the selector before invoking Zip.

Example fix

// before
Observable.Zip(firstStream, s2, s3, s4, selector); // firstStream == null
// after
var s1 = firstStream ?? Observable.Empty<FirstType>();
Observable.Zip(s1, s2, s3, s4, selector);
Defensive patterns

Strategy: validation

Validate before calling

if (source1 == null) source1 = Observable.Empty<TSource1>();

Type guard

bool IsValid<T>(IObservable<T> s) => s is not null;

Try / catch

try { return Observable.Zip(s1, s2, s3, s4, selector); }
catch (ArgumentNullException ex) when (ex.ParamName == "source1") { /* fall back to a default stream */ }

Prevention

When it happens

Trigger: Calling Observable.Zip(source1, source2, source3, source4, resultSelector) with null as the first observable.

Common situations: The primary stream from a service/repository returning null on failure; conditional pipeline construction skipping the first source; refactor merging two sources into four without updating all arguments.

Related errors


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

Appendix: source

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

        {
            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 (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return s_impl.Zip(source1, source2, source3, 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="TResult">The type of the elements in the result sequence, returned by the selector function.</typeparam>
        /// <param name="source1">First observable source.</param>
        /// <param name="source2">Second observable source.</param>
        /// <param name="source3">Third observable source.</param>
        /// <param name="source4">Fourth observable source.</param>
        /// <param name="resultSelector">Function to invoke for each series of elements at corresponding indexes in the sources.</param>

View on GitHub (pinned to 94b5d5ab91)