dotnet/reactive · error · ArgumentNullException
scheduler
Error message
scheduler
What it means
This time-based Skip overload requires an IAsyncScheduler to run the per-element duration timers; null is rejected at operator creation. Fix: pass a scheduler (e.g. TaskPoolAsyncScheduler.Default) or use the overload without an explicit scheduler.
Solutions
- Pass a valid scheduler such as TaskPoolAsyncScheduler.Default or the NewDefaultAsyncScheduler
- Fix DI registration so IAsyncScheduler is provided
- Use the two-argument Skip(source, duration) overload, which defaults to TaskPoolAsyncScheduler.Default
Example fix
// before source.Skip(TimeSpan.FromSeconds(1), null); // after source.Skip(TimeSpan.FromSeconds(1), TaskPoolAsyncScheduler.Default);
Defensive patterns
Strategy: validation
Validate before calling
if (scheduler == null) scheduler = TaskPoolAsyncScheduler.Default; var res = source.Skip(TimeSpan.FromSeconds(1), scheduler);
Type guard
bool IsValidScheduler(IAsyncScheduler s) => s != null;
Try / catch
try { var res = source.Skip(dur, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { res = source.Skip(dur); } // default scheduler overload Prevention
- Default to TaskPoolAsyncScheduler.Default when no scheduler is configured
- Verify DI registration for IAsyncScheduler at startup
- Prefer the two-argument overload when a custom scheduler is not needed
When it happens
Trigger: Calling Skip(source, duration, null), e.g. a scheduler field/property not yet initialized or a DI-resolved scheduler that failed to register.
Common situations: Missing DI registration for IAsyncScheduler; using a scheduler obtained from a service that returned null; forgetting to pass TaskPoolAsyncScheduler.Default explicitly.
Related errors
- Value cannot be null. (Parameter 'scheduler')
- Value cannot be null. (Parameter 'action')
- action (Parameter 'action')
- scheduler (Value cannot be null)
- action (Value cannot be null)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/96fe4f2f32d43a0e.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Skip.cs:66
duration,
static async (source, duration, observer) =>
{
var (sourceObserver, timer) = await AsyncObserver.Skip(observer, duration).ConfigureAwait(false);
var subscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, timer);
});
}
public static IAsyncObservable<TSource> Skip<TSource>(this IAsyncObservable<TSource> source, TimeSpan duration, IAsyncScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (duration < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(duration));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
if (duration == TimeSpan.Zero)
{
return source;
}
// REVIEW: May be easier to just use SkipUntil with a Timer parameter. Do we want Skip on the observer?
return CreateAsyncObservable<TSource>.From(
source,
(duration, scheduler),
static async (source, state, observer) =>
{
var (sourceObserver, timer) = await AsyncObserver.Skip(observer, state.duration).ConfigureAwait(false);
var subscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, timer);View on GitHub (pinned to 94b5d5ab91)