dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'scheduler')
Error message
Value cannot be null. (Parameter 'scheduler')
What it means
AsyncRx.NET's Append operator validates its arguments eagerly and throws ArgumentNullException when the scheduler parameter is null. Append needs a scheduler to emit the appended values on a controlled timeline, so a null scheduler makes the operator's contract unsatisfiable. The check happens at call time, not at subscription time.
Solutions
- Pass a concrete scheduler, e.g. AsyncScheduler.Default (or Scheduler.Default in the sync System.Reactive), instead of null.
- If the scheduler comes from DI/config, verify registration and resolve it before calling Append, failing fast if null.
- If the overload without a scheduler exists and immediate/implied scheduling is fine, call that overload instead.
- Add a guard or default: scheduler ?? AsyncScheduler.Default at the call site.
Example fix
// before
var result = source.Append(new[] { 4, 5 }, scheduler: null);
// after
var result = source.Append(new[] { 4, 5 }, AsyncScheduler.Default); Defensive patterns
Strategy: validation
Validate before calling
if (scheduler == null)
throw new InvalidOperationException("scheduler must be configured before calling Append"); Type guard
static bool HasScheduler(AsyncScheduler? s) => s is not null;
Try / catch
try
{
var q = source.Append(values, scheduler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler")
{
// fall back to default scheduler or report config failure
var q = source.Append(values, AsyncScheduler.Default);
} Prevention
- Register schedulers in DI and validate resolution at startup
- Never pass nullable scheduler fields directly; coalesce with AsyncScheduler.Default
- Prefer overloads without a scheduler when timing control is not needed
When it happens
Trigger: Calling ObservableExtensions.Append (the overload taking a scheduler, e.g. Append(source, values, scheduler) or Append(source, value, scheduler)) with scheduler passed as null, typically when the scheduler is sourced from a nullable field, config, or dependency injection that returned null.
Common situations: Dependency-injection container failing to register an IScheduler/AsyncScheduler implementation; a config lookup returning null for a scheduler name; passing the result of a helper method like GetScheduler() that returns null on failure; refactoring where the DefaultScheduler fallback was removed.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/73fd2ec84e5cac61.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Append.cs:269
{
foreach (var value in values)
{
await observer.OnNextAsync(value).ConfigureAwait(false);
}
await observer.OnCompletedAsync().ConfigureAwait(false);
}
);
}
public static (IAsyncObserver<TSource>, IAsyncDisposable) Append<TSource>(IAsyncObserver<TSource> observer, IAsyncScheduler scheduler, IEnumerable<TSource> values)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (values == null)
throw new ArgumentNullException(nameof(values));
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 =>
{
var e = default(IEnumerator<TSource>);
try
{
e = values.GetEnumerator();
}View on GitHub (pinned to 94b5d5ab91)