dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'observer')
Error message
Value cannot be null. (Parameter 'observer')
What it means
The AsyncObserver.SelectMany factory (observer-side overload taking IAsyncObserver<TResult> and a Func<TSource, IAsyncObservable<TResult>> selector) throws ArgumentNullException because the observer parameter was null. This overload adapts a downstream observer into a SelectMany pipeline; without an observer there is nothing to forward events to, so construction fails immediately.
Solutions
- Pass a valid IAsyncObserver<TResult> instance as the first argument.
- If composing, verify the upstream expression producing the observer (e.g. AsyncObserver.Create...) actually returned non-null.
- Use the higher-level AsyncObservable.SelectMany on the observable instead of manually wiring observer-side factories.
- Assert the observer argument at the call site before invoking AsyncObserver.SelectMany.
Example fix
// before var (obs, disp) = AsyncObserver.SelectMany<TSource, TResult>(null, x => inner); // after var downstream = AsyncObserver.Create<TResult>(onNextAsync, onErrorAsync, onCompletedAsync); var (obs, disp) = AsyncObserver.SelectMany(downstream, x => inner);
Defensive patterns
Strategy: validation
Validate before calling
if (observer is null) throw new ArgumentNullException(nameof(observer)); if (selector is null) throw new ArgumentNullException(nameof(selector));
Type guard
static bool IsValidObserverArgs<TSource, TResult>(
IAsyncObserver<TResult> observer,
Func<TSource, IAsyncObservable<TResult>> selector)
=> observer is not null && selector is not null; Try / catch
try
{
var (obs, disp) = AsyncObserver.SelectMany(observer, selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "observer")
{
observer = AsyncObserver.Create<TResult>(...); // substitute a no-op observer
} Prevention
- Always construct observers via AsyncObserver.Create or an operator, never hold nullable observer variables.
- Check the return of any method that yields an observer before passing it on.
- Favor the observable-level SelectMany + SubscribeAsync API to avoid manual observer wiring.
When it happens
Trigger: Calling AsyncObserver.SelectMany<TSource, TResult>(null, selector), or passing an observer variable that a factory/composition method returned as null.
Common situations: Building custom operator pipelines where the downstream observer comes from another operator's return value that silently returned null, misordered tuple construction of (observer, disposable) pairs, or typo'd variable assignment in observer-chain setup.
Related errors
- Value cannot be null. (Parameter 'selector')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/ec79065c95bc1422.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/SelectMany.cs:187
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)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
return SelectMany<TSource, TResult, TResult>(observer, x => new ValueTask<IAsyncObservable<TResult>>(selector(x)), (x, y) => new ValueTask<TResult>(y));
}
public static (IAsyncObserver<TSource>, IAsyncDisposable) SelectMany<TSource, TResult>(IAsyncObserver<TResult> observer, Func<TSource, ValueTask<IAsyncObservable<TResult>>> selector)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
return SelectMany<TSource, TResult, TResult>(observer, selector, (x, y) => new ValueTask<TResult>(y));
}
public static (IAsyncObserver<TSource>, IAsyncDisposable) SelectMany<TSource, TCollection, TResult>(IAsyncObserver<TResult> observer, Func<TSource, IAsyncObservable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
{View on GitHub (pinned to 94b5d5ab91)