dotnet/reactive · error · ArgumentNullException
null (Parameter 'scheduler')
Error message
null (Parameter 'scheduler')
What it means
The Append operator's disposer-returning overload (IAsyncObserver, value, IAsyncScheduler) requires a non-null scheduler because appended values are emitted on that scheduler. System.Reactive.Async guards its public API surface eagerly, throwing ArgumentNullException with C# 10's raw parameter-name message format ("null (Parameter 'scheduler')") at the operator factory rather than failing later inside the async pipeline. Passing null means the operator could never schedule the appended value, so it fails fast.
Solutions
- Pass a concrete IAsyncScheduler such as AsyncScheduler.Default (or AsyncScheduler.Immediate / a task-pool scheduler) at the call site.
- If the scheduler comes from a caller or DI container, register/initialize it before constructing the Append operator.
- Add a null check with a default at the call boundary: scheduler ??= AsyncScheduler.Default.
Example fix
// before var (obs, disp) = AsyncObservable.Append(observer, 42, null); // after var (obs, disp) = AsyncObservable.Append(observer, 42, AsyncScheduler.Default);
Defensive patterns
Strategy: validation
Validate before calling
if (scheduler is null) throw new InvalidOperationException("Append requires a scheduler; pass AsyncScheduler.Default.");
var (obs, disp) = AsyncObservable.Append(observer, value, scheduler); Type guard
bool HasScheduler(IAsyncScheduler? s) => s is not null;
Try / catch
try { var (obs, disp) = AsyncObservable.Append(observer, value, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { scheduler = AsyncScheduler.Default; /* retry */ } Prevention
- Default optional schedulers with `scheduler ??= AsyncScheduler.Default` at API boundaries
- Verify DI registrations for any injected IAsyncScheduler
- Never pass null where an overload exists without the scheduler parameter
When it happens
Trigger: Calling AsyncObservable.Append(observer, value, scheduler) with scheduler == null, e.g. Append(observer, value, null) or a variable assigned from a lookup that returned null.
Common situations: Resolving the scheduler from a DI container or config that was not registered; caching a scheduler in a field whose initialization was skipped; migrating code that previously used a synchronous overload and passing null where a scheduler is now required.
Related errors
- null (Parameter 'values')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'values')
- action
- functionAsync
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/145099e9af0ac849.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Append.cs:156
throw new ArgumentNullException(nameof(observer));
return Create<TSource>(
observer.OnNextAsync,
observer.OnErrorAsync,
async () =>
{
await observer.OnNextAsync(value).ConfigureAwait(false);
await observer.OnCompletedAsync().ConfigureAwait(false);
}
);
}
public static (IAsyncObserver<TSource>, IAsyncDisposable) Append<TSource>(IAsyncObserver<TSource> observer, TSource value, IAsyncScheduler scheduler)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
var d = new SingleAssignmentAsyncDisposable();
return
(
Create<TSource>(
observer.OnNextAsync,
observer.OnErrorAsync,
async () =>
{
var task = await scheduler.ScheduleAsync(async ct =>
{
if (!ct.IsCancellationRequested)
{
await observer.OnNextAsync(value).RendezVous(scheduler, ct);
await observer.OnCompletedAsync().RendezVous(scheduler, ct);
}
}).ConfigureAwait(false);View on GitHub (pinned to 94b5d5ab91)