dotnet/reactive · error · ArgumentNullException
scheduler
Error message
scheduler
What it means
The scheduler-taking DelaySubscription overload throws ArgumentNullException because the scheduler argument is null. The scheduler determines when the delayed Subscribe happens; without one the operator cannot function, so the null is rejected up front rather than at subscription time.
Solutions
- Pass TaskPoolAsyncScheduler.Default or another non-null IAsyncScheduler.
- Use the DelaySubscription(source, dueTime) overload that defaults to TaskPoolAsyncScheduler.Default.
- Ensure DI/config-provided schedulers are registered and resolved before composition.
Example fix
// before return source.DelaySubscription(due, cfg.Scheduler); // cfg.Scheduler null // after return source.DelaySubscription(due, cfg.Scheduler ?? TaskPoolAsyncScheduler.Default);
Defensive patterns
Strategy: validation
Validate before calling
var scheduler = cfg.Scheduler ?? TaskPoolAsyncScheduler.Default; return source.DelaySubscription(due, scheduler);
Type guard
static IAsyncScheduler SchedulerOrDefault(IAsyncScheduler? s) => s ?? TaskPoolAsyncScheduler.Default;
Try / catch
try { return source.DelaySubscription(due, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { return source.DelaySubscription(due, TaskPoolAsyncScheduler.Default); } Prevention
- Coalesce configured schedulers with TaskPoolAsyncScheduler.Default.
- Validate scheduler configuration at app startup.
- Prefer the two-argument overload when no custom scheduler is required.
When it happens
Trigger: Calling DelaySubscription<TSource>(source, dueTime, null) — null IAsyncScheduler on the second overload.
Common situations: Scheduler resolved from configuration that was absent; passing a test scheduler variable that is only initialized in test mode; forgetting the default-arg overload exists.
Related errors
- scheduler
- source
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'error')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/514a89628231f57f.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/DelaySubscription.cs:25
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
return DelaySubscription(source, dueTime, TaskPoolAsyncScheduler.Default);
}
public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime, IAsyncScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return Create(
source,
(dueTime, scheduler),
static async (source, state, observer) =>
{
var d = new CompositeAsyncDisposable();
var task = await state.scheduler.ScheduleAsync(async ct =>
{
var inner = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
await d.AddAsync(inner).ConfigureAwait(false);
}, state.dueTime).ConfigureAwait(false);
await d.AddAsync(task).ConfigureAwait(false);
return d;
});View on GitHub (pinned to 94b5d5ab91)