dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'resultSelector')

Error message

Value cannot be null. (Parameter 'resultSelector')

What it means

WithLatestFrom's resultSelector is invoked for every source value to combine it with the latest value of the second stream. A null selector cannot be invoked, so the operator throws ArgumentNullException with parameter name 'resultSelector' during eager validation in first.WithLatestFrom(second, resultSelector).

Solutions

  1. Pass a concrete selector, e.g. (first, second) => (first, second) for the default pairing behavior.
  2. If no projection is needed, use the two-parameter WithLatestFrom(first, second) overload instead.
  3. Fix the delegate resolution (DI registration, config binding) so it produces a non-null Func.
  4. Add a null check with a clear message before composing the pipeline.

Example fix

// before
var result = first.WithLatestFrom(second, null);
// after
var result = first.WithLatestFrom(second, (f, s) => (f, s));
Defensive patterns

Strategy: validation

Validate before calling

if (resultSelector is null) throw new ArgumentNullException(nameof(resultSelector));
var result = first.WithLatestFrom(second, resultSelector);

Type guard

bool HasSelector<T1, T2, R>(Func<T1, T2, R> f) => f is not null;

Try / catch

try
{
    var result = first.WithLatestFrom(second, resultSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "resultSelector")
{
    // fall back to tuple-pairing default selector
    var result = first.WithLatestFrom(second, (f, s) => (f, s));
}

Prevention

When it happens

Trigger: Calling first.WithLatestFrom(second, resultSelector) with a null delegate, e.g. a selector resolved from configuration/DI that failed to bind, or a lambda variable left null in conditional pipeline construction.

Common situations: Reflection-based or DI-based composition where the projection delegate could not be created; config-driven pipelines with an invalid or missing selector key; refactors renaming the selector and defaulting it to null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/WithLatestFrom.cs:43

                    var (firstObserver, secondObserver) = AsyncObserver.WithLatestFrom(observer);

                    // REVIEW: Consider concurrent subscriptions.

                    var firstSubscription = await first.SubscribeSafeAsync(firstObserver).ConfigureAwait(false);
                    var secondSubscription = await second.SubscribeSafeAsync(secondObserver).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(firstSubscription, secondSubscription);
                });
        }

        public static IAsyncObservable<TResult> WithLatestFrom<TFirst, TSecond, TResult>(this IAsyncObservable<TFirst> first, IAsyncObservable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
        {
            if (first == null)
                throw new ArgumentNullException(nameof(first));
            if (second == null)
                throw new ArgumentNullException(nameof(second));
            if (resultSelector == null)
                throw new ArgumentNullException(nameof(resultSelector));

            return CreateAsyncObservable<TResult>.From(
                first,
                (second, resultSelector),
                static async (first, state, observer) =>
                {
                    var (firstObserver, secondObserver) = AsyncObserver.WithLatestFrom(observer, state.resultSelector);

                    // REVIEW: Consider concurrent subscriptions.

                    var firstSubscription = await first.SubscribeSafeAsync(firstObserver).ConfigureAwait(false);
                    var secondSubscription = await state.second.SubscribeSafeAsync(secondObserver).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(firstSubscription, secondSubscription);
                });
        }

        public static IAsyncObservable<TResult> WithLatestFrom<TFirst, TSecond, TResult>(this IAsyncObservable<TFirst> first, IAsyncObservable<TSecond> second, Func<TFirst, TSecond, ValueTask<TResult>> resultSelector)

View on GitHub (pinned to 94b5d5ab91)