dotnet/reactive · error · ArgumentNullException
subscribeScheduler
Error message
subscribeScheduler
What it means
SubscribeOn(source, subscribeScheduler, disposeScheduler) validates each scheduler. Passing a null subscribeScheduler throws ArgumentNullException("subscribeScheduler") because subscription must be dispatched onto it.
Solutions
- Pass a concrete subscribe scheduler, or call the single-scheduler overload SubscribeOn(source, scheduler) which uses the same scheduler for both.
- Fix the null initialization of the scheduler variable.
- Validate both schedulers before calling (see validation pattern).
Example fix
// before var obs = source.SubscribeOn(null, disposeScheduler); // after var obs = source.SubscribeOn(subscribeScheduler ?? AsyncScheduler.DefaultScheduler, disposeScheduler);
Defensive patterns
Strategy: validation
Validate before calling
if (subscribeScheduler == null)
throw new ArgumentNullException(nameof(subscribeScheduler));
if (disposeScheduler == null)
throw new ArgumentNullException(nameof(disposeScheduler)); Type guard
bool SchedulersValid(IAsyncScheduler? s, IAsyncScheduler? d) => s is not null && d is not null;
Try / catch
try
{
var obs = source.SubscribeOn(subscribeScheduler, disposeScheduler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "subscribeScheduler")
{
logger.LogError(ex, "Null subscribe scheduler");
obs = source.SubscribeOn(AsyncScheduler.DefaultScheduler, disposeScheduler);
} Prevention
- Default both scheduler parameters at the call site before invoking.
- Keep scheduler pairs in a small record/struct validated at construction.
- Prefer the single-scheduler overload when both phases share one scheduler.
When it happens
Trigger: Calling source.SubscribeOn(source, null, disposeScheduler) — typically when the subscribe scheduler was meant to be inferred or was misassigned; also happens when constructing the tuple of schedulers from config where one entry is missing.
Common situations: Config only defines a dispose scheduler; a scheduler field initialized asynchronously and read before assignment; copy-paste from the single-scheduler overload leaving one argument null.
Related errors
- Argument cannot be null (Parameter name: scheduler)
- disposeScheduler
- nameof(scheduler)
- new ArgumentNullException(nameof(scheduler))
- new ArgumentNullException(nameof(timeSelector))
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/e4439c1e55134bc2.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/SubscribeOn.cs:27
{
public partial class AsyncObservable
{
public static IAsyncObservable<TSource> SubscribeOn<TSource>(this IAsyncObservable<TSource> source, IAsyncScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return SubscribeOn(source, scheduler, scheduler);
}
public static IAsyncObservable<TSource> SubscribeOn<TSource>(this IAsyncObservable<TSource> source, IAsyncScheduler subscribeScheduler, IAsyncScheduler disposeScheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (subscribeScheduler == null)
throw new ArgumentNullException(nameof(subscribeScheduler));
if (disposeScheduler == null)
throw new ArgumentNullException(nameof(disposeScheduler));
return CreateAsyncObservable<TSource>.From(
source,
(subscribeScheduler, disposeScheduler),
static async (source, state, observer) =>
{
var m = new SingleAssignmentAsyncDisposable();
var d = new SerialAsyncDisposable();
await d.AssignAsync(m).ConfigureAwait(false);
var scheduled = await state.subscribeScheduler.ScheduleAsync(async ct =>
{
var subscription = await source.SubscribeSafeAsync(observer).RendezVous(state.subscribeScheduler, ct);
var scheduledDispose = AsyncDisposable.Create(async () =>View on GitHub (pinned to 94b5d5ab91)