dotnet/reactive · error · ArgumentNullException
scheduler
Error message
scheduler
What it means
Expand(source, selector, scheduler) uses the IScheduler to control timing/concurrency of recursive expansion. A null scheduler throws ArgumentNullException immediately. Passing Scheduler.Default or an explicit scheduler resolves it.
Solutions
- Pass Scheduler.Default, Scheduler.TaskPool, or Scheduler.CurrentThread
- Drop the scheduler overload and call the two-argument Expand(source, selector), which uses the default scheduler
- Fix initialization/DI ordering so the injected scheduler is set before pipelines are built
Example fix
// before var expanded = source.Expand(x => Next(x), sched); // sched null // after var expanded = source.Expand(x => Next(x), sched ?? Scheduler.Default);
Defensive patterns
Strategy: validation
Validate before calling
if (scheduler == null) throw new ArgumentNullException(nameof(scheduler), "Expand requires a scheduler; use Scheduler.Default.");
Type guard
bool IsValidScheduler(IScheduler s) => s is not null;
Try / catch
try { var expanded = source.Expand(selector, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { log.Error("Scheduler not provided for Expand", ex); } Prevention
- Use the two-argument Expand overload when no custom scheduler is needed
- Coalesce injected schedulers with Scheduler.Default
- Add DI startup assertions that IScheduler resolves non-null
When it happens
Trigger: Calling Expand with scheduler = null, typically from an uninitialized injected scheduler or a static property that has not been assigned.
Common situations: Missing IScheduler DI registration, unit tests passing null instead of TestScheduler, app-startup ordering where the scheduler field is read before initialization.
Related errors
- throw new ArgumentNullException(nameof(scheduler));
- throw new ArgumentNullException(nameof(scheduler));
- Value cannot be null. (Parameter 'scheduler')
- source
- scheduler (Value cannot be null)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/686b41589a77e57b.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/ObservableEx.cs:87
/// <param name="scheduler">Scheduler on which to perform the expansion by enumerating the internal queue of obtained sequences.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> or <paramref name="scheduler"/> is null.</exception>
[Experimental]
public static IObservable<TSource> Expand<TSource>(this IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector, IScheduler scheduler)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (selector == null)
{
throw new ArgumentNullException(nameof(selector));
}
if (scheduler == null)
{
throw new ArgumentNullException(nameof(scheduler));
}
return s_impl.Expand(source, selector, scheduler);
}
/// <summary>
/// Expands an observable sequence by recursively invoking selector.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>
/// <param name="source">Source sequence with the initial elements.</param>
/// <param name="selector">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>
[Experimental]
public static IObservable<TSource> Expand<TSource>(this IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector)
{
if (source == null)
{View on GitHub (pinned to 94b5d5ab91)