dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source')

Error message

Value cannot be null. (Parameter 'source')

What it means

SelectMany (the fully async overload with ValueTask-returning collectionSelector and resultSelector) throws ArgumentNullException('source') because the source IAsyncObservable<TSource> was null. Validation is performed synchronously before CreateAsyncObservable builds the pipeline, so the failure is immediate and no resources are leaked. The message 'Value cannot be null. (Parameter 'source')' is the standard .NET ArgumentNullException rendering.

Solutions

  1. Await the async initialization that assigns the source before composing
  2. Fix the producer to return AsyncObservable.Empty<TSource>() instead of null
  3. Add an explicit null guard with a descriptive exception near the source creation

Example fix

// before
var src = _lazySource; // still null, init not awaited
var result = src.SelectMany(cs, rs);
// after
await InitializeAsync();
var src = _lazySource ?? AsyncObservable.Empty<TSource>();
var result = src.SelectMany(cs, rs);
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 IsObservableReady<T>(IAsyncObservable<T>? o) => o is not null;

Try / catch

try { var result = src.SelectMany(asyncCs, asyncRs); }
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{ /* await async initialization or substitute an empty observable */ }

Prevention

When it happens

Trigger: Calling SelectMany<TSource,TCollection,TResult>(source, Func<TSource,int,ValueTask<IAsyncObservable<TCollection>>>, Func<TSource,int,TCollection,int,ValueTask<TResult>>) with source == null; e.g. a null-returning async factory or a field assigned in an async init that has not run.

Common situations: Async initialization order bugs (subscription before initialization completes); producers that return null instead of an empty observable on error; missing DI registration.

Related errors


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

Appendix: source

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

                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 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);
                });
        }
    }

View on GitHub (pinned to 94b5d5ab91)