dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'onNextAsync')
Error message
Value cannot be null. (Parameter 'onNextAsync')
What it means
The AsyncObserver constructor requires concrete delegate implementations for onNextAsync, onErrorAsync, and onCompletedAsync; it null-checks each and throws ArgumentNullException naming the offending parameter. A null onNextAsync would make it impossible to forward incoming elements, so construction fails immediately (line 17).
Solutions
- Supply a real next handler: ValueTask-returning lambda such as async x => await HandleAsync(x).
- Use AsyncObserver.Create(onNextAsync, onErrorAsync, onCompletedAsync) or the SubscribeAsync extensions, which document the same null requirements.
- Use the built-in no-op/empty observers (e.g. AsyncObserver.Empty<T>() style helpers) if you need an inert observer.
- If onNext truly should do nothing, pass _ => default instead of null.
Example fix
// before
var observer = new AsyncObserver<int>(null, ex => default, () => default);
// after
var observer = new AsyncObserver<int>(x => { Console.WriteLine(x); return default; }, ex => default, () => default); Defensive patterns
Strategy: validation
Validate before calling
if (onNextAsync == null || onErrorAsync == null || onCompletedAsync == null)
throw new ArgumentException("AsyncObserver requires non-null onNextAsync, onErrorAsync, and onCompletedAsync delegates.");
var observer = new AsyncObserver<T>(onNextAsync, onErrorAsync, onCompletedAsync); Try / catch
try
{
var observer = new AsyncObserver<T>(onNextAsync, onErrorAsync, onCompletedAsync);
}
catch (ArgumentNullException ex) when (ex.ParamName == "onNextAsync")
{
observer = new AsyncObserver<T>(_ => default, onErrorAsync, onCompletedAsync);
} Prevention
- Prefer AsyncObserver.Create or SubscribeAsync extensions over constructing AsyncObserver directly.
- Use no-op delegates (_ => default) instead of null when a handler is intentionally empty.
- Validate delegate arguments in factory/wrapper code before passing them through.
When it happens
Trigger: new AsyncObserver<T>(null, onErrorAsync, onCompletedAsync) — constructing the observer directly with a null next-handler delegate.
Common situations: Building custom observers by hand instead of using the AsyncObserver.Create factory or SubscribeAsync extension helpers; generic factory code that passes through a caller-supplied (possibly null) delegate; refactors that changed a lambda to null intending to remove behavior.
Related errors
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'context')
- Value cannot be null. (Parameter 'disposable')
- Value cannot be null. (Parameter 'begin')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/cfc8b6a0f33ff35b.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/AsyncObserver.cs:17
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
namespace System.Reactive
{
public class AsyncObserver<T> : AsyncObserverBase<T>
{
private readonly Func<T, ValueTask> _onNextAsync;
private readonly Func<Exception, ValueTask> _onErrorAsync;
private readonly Func<ValueTask> _onCompletedAsync;
public AsyncObserver(Func<T, ValueTask> onNextAsync, Func<Exception, ValueTask> onErrorAsync, Func<ValueTask> onCompletedAsync)
{
_onNextAsync = onNextAsync ?? throw new ArgumentNullException(nameof(onNextAsync));
_onErrorAsync = onErrorAsync ?? throw new ArgumentNullException(nameof(onErrorAsync));
_onCompletedAsync = onCompletedAsync ?? throw new ArgumentNullException(nameof(onCompletedAsync));
}
protected override ValueTask OnCompletedAsyncCore() => _onCompletedAsync();
protected override ValueTask OnErrorAsyncCore(Exception error) => _onErrorAsync(error ?? throw new ArgumentNullException(nameof(error)));
protected override ValueTask OnNextAsyncCore(T value) => _onNextAsync(value);
}
}
View on GitHub (pinned to 94b5d5ab91)