dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'resultSelector')

Error message

Value cannot be null. (Parameter 'resultSelector')

What it means

The async SelectMany operator on IAsyncObservable<TSource> throws ArgumentNullException because its resultSelector parameter was null. This operator requires a function that combines each source element with each inner-collection element to produce the final result; without it the operator cannot be constructed. The library validates all delegate arguments eagerly at operator-creation time rather than failing later during subscription.

Solutions

  1. Pass a non-null resultSelector lambda, e.g. (x, y) => Combine(x, y).
  2. If the result is just the inner element, use the two-argument overload SelectMany(source, collectionSelector) instead of passing a null selector.
  3. Check where the delegate comes from (config, dictionary lookup, optional parameter default) and default it to a valid function instead of null.
  4. Guard the call site: if (resultSelector == null) throw/log before invoking SelectMany so the failure points at your code.

Example fix

// before
var qs = AsyncObservable.SelectMany(source, x => GetInner(x), null);

// after
var qs = AsyncObservable.SelectMany(source, x => GetInner(x), (src, inner) => new Result(src.Id, inner));
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new ArgumentNullException(nameof(source));
if (collectionSelector is null) throw new ArgumentNullException(nameof(collectionSelector));
if (resultSelector is null) throw new ArgumentNullException(nameof(resultSelector));

Type guard

static bool IsValidSelectManyArgs<TSource, TCollection, TResult>(
    IAsyncObservable<TSource> source,
    Func<TSource, IAsyncObservable<TCollection>> collectionSelector,
    Func<TSource, TCollection, TResult> resultSelector)
    => source is not null && collectionSelector is not null && resultSelector is not null;

Try / catch

try
{
    var qs = AsyncObservable.SelectMany(source, collectionSelector, resultSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "resultSelector")
{
    // provide default projection or surface config error
    resultSelector = (src, inner) => default;
}

Prevention

When it happens

Trigger: Calling AsyncObservable.SelectMany(source, collectionSelector, resultSelector) with a null third argument, e.g. SelectMany(source, x => inner, (Func<TSource,TCollection,TResult>)null), or passing a resultSelector variable that was never assigned.

Common situations: Conditional delegate assignment (resultSelector only assigned in one branch), passing the output of a factory/lookup method that returned null, refactoring from a two-argument SelectMany overload to the three-argument one and forgetting the extra argument, or dynamic composition where a selector map has no entry.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/SelectMany.cs:166

                (collectionSelector, resultSelector),
                static async (source, state, observer) =>
                {
                    var (sink, inner) = AsyncObserver.SelectMany(observer, state.collectionSelector, state.resultSelector);

                    var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(subscription, inner);
                });
        }

        public static IAsyncObservable<TResult> SelectMany<TSource, TCollection, TResult>(this IAsyncObservable<TSource> source, Func<TSource, int, ValueTask<IAsyncObservable<TCollection>>> collectionSelector, Func<TSource, int, TCollection, int, ValueTask<TResult>> resultSelector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (collectionSelector == null)
                throw new ArgumentNullException(nameof(collectionSelector));
            if (resultSelector == null)
                throw new ArgumentNullException(nameof(resultSelector));

            return CreateAsyncObservable<TResult>.From(
                source,
                (collectionSelector, resultSelector),
                static async (source, state, observer) =>
                {
                    var (sink, inner) = AsyncObserver.SelectMany(observer, state.collectionSelector, state.resultSelector);

                    var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(subscription, inner);
                });
        }
    }

    public partial class AsyncObserver
    {
        public static (IAsyncObserver<TSource>, IAsyncDisposable) SelectMany<TSource, TResult>(IAsyncObserver<TResult> observer, Func<TSource, IAsyncObservable<TResult>> selector)

View on GitHub (pinned to 94b5d5ab91)