dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'selector')
Error message
Value cannot be null. (Parameter 'selector')
What it means
The 7-source Zip overload with a result selector Func<T1..T7, ValueTask<TResult>> throws ArgumentNullException('selector') when the selector delegate is null. After checking all seven sources, the operator requires a non-null function to combine the zipped elements (it is invoked by AsyncObserver.Zip to project each tuple).
Solutions
- Supply a valid async selector, e.g. (t1, t2, t3, t4, t5, t6, t7) => ValueTask.FromResult(t1 + t7).
- If no projection is needed, use the plain 7-source Zip overload that returns a tuple instead of passing null.
- Guard the selector variable for null before calling Zip.
Example fix
// before
Func<T1,T2,T3,T4,T5,T6,T7,ValueTask<TResult>> selector = maybeSelector;
var zipped = AsyncObservable.Zip(s1, s2, s3, s4, s5, s6, s7, selector);
// after
var zipped = AsyncObservable.Zip(s1, s2, s3, s4, s5, s6, s7,
maybeSelector ?? ((t1, t2, t3, t4, t5, t6, t7) => ValueTask.FromResult(project(t1, t2, t3, t4, t5, t6, t7)))); Defensive patterns
Strategy: validation
Validate before calling
if (selector == null) throw new InvalidOperationException("zip result selector must be provided"); Type guard
bool IsValidSelector<T1,T2,T3,T4,T5,T6,T7,TResult>(Func<T1,T2,T3,T4,T5,T6,T7,ValueTask<TResult>> f) => f is not null;
Try / catch
try
{
var zipped = AsyncObservable.Zip(s1, s2, s3, s4, s5, s6, s7, selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "selector")
{
logger.LogError(ex, "zip selector was null");
} Prevention
- Pass selector lambdas inline rather than through nullable variables
- Use the tuple-returning Zip overload when no projection is needed
- Initialize Func fields at declaration or make them required constructor parameters
When it happens
Trigger: Calling AsyncObservable.Zip(s1..s7, (Func<T1,...,T7,ValueTask<TResult>>)null) - passing null where the async result-selector lambda should be.
Common situations: A selector stored in a variable or returned from a factory was null; conditional lambda assignment skipped; refactoring from the no-selector overload to the selector overload left the argument empty.
Related errors
- throw new ArgumentNullException(nameof(selector));
- Value cannot be null. (Parameter 'selector')
- Value cannot be null. (Parameter 'keySelector')
- Value cannot be null. (Parameter 'source4')
- Value cannot be null. (Parameter 'source5')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/db55dc58b6e1d8b8.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Zip.Generated.cs:508
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, 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();
var (observer1, observer2, observer3, observer4, observer5, observer6, observer7) = 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();
await Task.WhenAll(sub1, sub2, sub3, sub4, sub5, sub6, sub7).ConfigureAwait(false);
return d;View on GitHub (pinned to 94b5d5ab91)