dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'collectionSelector')
Error message
Value cannot be null. (Parameter 'collectionSelector')
What it means
SelectMany (fully async overload) throws ArgumentNullException('collectionSelector') because the ValueTask-returning collectionSelector delegate was null. The library validates all arguments eagerly at the SelectMany call site, so this surfaces immediately rather than when the first element is processed. Supply a valid async collection selector to construct the operator.
Solutions
- Provide a non-null Func<TSource,int,ValueTask<IAsyncObservable<TCollection>>> collectionSelector
- If inner sequences are optional, pass an async lambda returning an empty observable
- Null-check the resolved delegate at composition time and fail with context
Example fix
// before var result = source.SelectMany(_selectorResolver(), rs); // resolver returned null // after var cs = _selectorResolver() ?? (async (x, i) => ValueTask.FromResult(AsyncObservable.Empty<TCollection>())); var result = source.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 IsValidAsyncCollectionSelector<TSource,TCollection>(Func<TSource,int,ValueTask<IAsyncObservable<TCollection>>>? cs) => cs is not null;
Try / catch
try { var result = source.SelectMany(asyncCs, asyncRs); }
catch (ArgumentNullException ex) when (ex.ParamName == "collectionSelector")
{ /* resolve/supply the async collection selector */ } Prevention
- Guard DI/config-resolved delegates with ?? empty-observable fallbacks
- Prefer method groups over nullable delegate lookups
- Test ValueTask overload call sites explicitly after migrations
- Fail loudly with context when a delegate resolver returns null
When it happens
Trigger: Calling SelectMany<TSource,TCollection,TResult>(source, collectionSelector, resultSelector) where collectionSelector == null; common when the inner-observable factory is resolved from DI/config and the resolution returned null.
Common situations: Configuration-driven pipelines where the selector is optional and unset; refactors that swapped Task-returning lambdas for ValueTask ones and dropped the argument; mocks returning null delegates.
Related errors
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'predicate')
- Value cannot be null. (Parameter 'observer')
- predicate
- source
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/e51bb077c437b9cd.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/SelectMany.cs:164
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);
});
}
}
public partial class AsyncObserverView on GitHub (pinned to 94b5d5ab91)