dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'asyncOperationSelector')

Error message

Value cannot be null. (Parameter 'asyncOperationSelector')

What it means

This SelectMany overload throws ArgumentNullException when the asyncOperationSelector delegate is null. The message text ('Value cannot be null. (Parameter 'asyncOperationSelector')') is the standard runtime-rendered form of ArgumentNullException. The delegate is required to map each element to a WinRT IAsyncOperation, so Rx fails fast before subscription.

Solutions

  1. Provide a non-null asyncOperationSelector, e.g. x => x.GetOperationAsync().
  2. Ensure DI/config actually resolves the selector delegate before composing.
  3. If you do not need the async projection, use the single-delegate SelectMany overload instead of passing null.

Example fix

// before
var q = source.SelectMany(null, (x, r) => r.Value);
// after
var q = source.SelectMany(
    (Item x) => x.GetOperationAsync(),
    (Item x, OpResult r) => r.Value);
Defensive patterns

Strategy: validation

Validate before calling

if (asyncOperationSelector is null) throw new InvalidOperationException("asyncOperationSelector must be configured");

Type guard

static bool HasSelectors<T, A, R>(Func<T, IAsyncOperation<A>>? opSel, Func<T, A, R>? resultSel) => opSel is not null && resultSel is not null;

Try / catch

try { var q = source.SelectMany(asyncOpSelector, resultSelector); }
catch (ArgumentNullException ex) when (ex.ParamName == "asyncOperationSelector") { /* log missing selector configuration */ }

Prevention

When it happens

Trigger: Calling source.SelectMany<TSource, TAsyncOperationResult, TResult>(asyncOperationSelector, resultSelector) where asyncOperationSelector is null.

Common situations: A configured selector dependency not registered in DI; a dictionary of per-type selectors missing a key and returning null; mistakenly passing null in a two-delegate call intending to skip the intermediate projection.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive.WindowsRuntime/System.Reactive.Linq/WindowsObservable.StandardSequenceOperators.cs:88

        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TAsyncOperationResult">The type of the results produced by the projected asynchronous operations.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence, obtained by using the selector to combine source sequence elements with their corresponding intermediate asynchronous operation results.</typeparam>
        /// <param name="source">An observable sequence of elements to project.</param>
        /// <param name="asyncOperationSelector">A transform function to apply to each element.</param>
        /// <param name="resultSelector">A transform function to apply to each element of the intermediate sequence.</param>
        /// <returns>An observable sequence whose elements are the result of obtaining an asynchronous operation for each element of the input sequence and then mapping the asynchronous operation's result and its corresponding source element to a result element.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="asyncOperationSelector"/> or <paramref name="resultSelector"/> is null.</exception>
        /// <remarks>This overload supports using LINQ query comprehension syntax in C# and Visual Basic to compose observable sequences and Windows Runtime asynchronous operations, without requiring manual conversion of the asynchronous operations to observable sequences using <see cref="AsyncInfoObservableExtensions.ToObservable{TResult}(IAsyncOperation{TResult})"/>.</remarks>
        public static IObservable<TResult> SelectMany<TSource, TAsyncOperationResult, TResult>(this IObservable<TSource> source, Func<TSource, IAsyncOperation<TAsyncOperationResult>> asyncOperationSelector, Func<TSource, TAsyncOperationResult, TResult> resultSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (asyncOperationSelector == null)
            {
                throw new ArgumentNullException(nameof(asyncOperationSelector));
            }

            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return source.SelectMany(x => asyncOperationSelector(x).ToObservable(), resultSelector);
        }

        /// <summary>
        /// Projects each element of an observable sequence to a Windows Runtime asynchronous operation, invokes the result selector for the source element and the asynchronous operation result, and merges the results into one observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TAsyncOperationResult">The type of the results produced by the projected asynchronous operations.</typeparam>
        /// <typeparam name="TAsyncOperationProgress">The type of the reported progress objects, which get ignored by this query operator.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence, obtained by using the selector to combine source sequence elements with their corresponding intermediate asynchronous operation results.</typeparam>
        /// <param name="source">An observable sequence of elements to project.</param>

View on GitHub (pinned to 94b5d5ab91)