dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'source3')
Error message
Value cannot be null. (Parameter 'source3')
What it means
The Observable.Zip three-source overload throws ArgumentNullException when resultSelector is null. All source sequences were non-null; the combining function itself is the missing argument. Rx requires an explicit selector because it defines the output type and combination logic. Provide a non-null Func<TSource1,TSource2,TSource3,TResult>.
Solutions
- Pass a valid lambda or method group as the result selector.
- If the selector is resolved dynamically, default it (e.g. selector ?? ((a,b,c) => default(TResult))).
- Check intermediate delegate fields/parameters for null before forwarding them to Zip.
Example fix
// before Observable.Zip(a, b, c, mySelector); // mySelector is null // after var selector = mySelector ?? ((int x, int y, int z) => x + y + z); Observable.Zip(a, b, c, selector);
Defensive patterns
Strategy: validation
Validate before calling
if (resultSelector == null) throw new InvalidOperationException("resultSelector must be provided"); Type guard
bool IsValid<T1,T2,T3,TResult>(Func<T1,T2,T3,TResult> f) => f is not null;
Try / catch
try { return Observable.Zip(a, b, c, resultSelector); }
catch (ArgumentNullException ex) when (ex.ParamName == "resultSelector") { /* supply default selector */ } Prevention
- Never store selectors in fields that can be null; initialize them inline
- When resolving delegates from DI/config, always coalesce to a default
- Mark selector parameters as required in helper wrappers
When it happens
Trigger: Calling Observable.Zip(source1, source2, source3, resultSelector) with a null selector delegate.
Common situations: Storing the selector in a variable resolved from config/DI that was never assigned; passing a method group from a class whose method is null via a delegate field; generic helper code forwarding a null selector parameter.
Related errors
- Value cannot be null. (Parameter 'source4')
- Value cannot be null. (Parameter 'source8')
- Value cannot be null. (Parameter 'source1')
- Value cannot be null. (Parameter 'source2')
- Value cannot be null. (Parameter 'resultSelector')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/c4e36273931b17d1.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.Zip.cs:38
/// <param name="source3">Third observable source.</param>
/// <param name="resultSelector">Function to invoke for each series of elements at corresponding indexes in the sources.</param>
/// <returns>An observable sequence containing the result of combining elements of the sources using the specified result selector function.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source1"/> or <paramref name="source2"/> or <paramref name="source3"/> or <paramref name="resultSelector"/> is null.</exception>
public static IObservable<TResult> Zip<TSource1, TSource2, TSource3, TResult>(this IObservable<TSource1> source1, IObservable<TSource2> source2, IObservable<TSource3> source3, Func<TSource1, TSource2, TSource3, TResult> resultSelector)
{
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>View on GitHub (pinned to 94b5d5ab91)