dotnet/reactive · error · ArgumentNullException
scheduler
Error message
scheduler
What it means
TakeLast(source, count, scheduler) throws ArgumentNullException("scheduler") because the overload requires an explicit IAsyncScheduler to schedule the timing window. The Rx.NET Async operators validate all reference arguments eagerly at call time rather than surfacing nulls later inside the subscription pipeline. Passing a null scheduler is a programming error, so it fails fast with the parameter name.
Solutions
- Pass a concrete IAsyncScheduler instance, e.g. the library's default/scheduler provider for your concurrency model
- Use the TakeLast(source, count) overload instead if no scheduler customization is needed
- Guard or assert the scheduler variable before calling, ensuring DI resolution produced a non-null instance
Example fix
// before var result = source.TakeLast(5, (IAsyncScheduler)null); // after var result = source.TakeLast(5, scheduler); // scheduler resolved from provider/DI // or: var result = source.TakeLast(5);
Defensive patterns
Strategy: validation
Validate before calling
if (scheduler is null) throw new InvalidOperationException("scheduler must be provided before calling TakeLast");
var result = source.TakeLast(5, scheduler); Type guard
bool HasScheduler(IAsyncScheduler? s) => s is not null;
Try / catch
try { var r = source.TakeLast(5, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "scheduler") { /* fall back to parameterless overload */ var r = source.TakeLast(5); } Prevention
- Prefer the shorter TakeLast overloads unless you truly need scheduler control
- Resolve schedulers from a single non-null provider
- Add unit tests that construct operator pipelines through DI to catch null services
When it happens
Trigger: Calling TakeLast with a non-null source and non-negative count but scheduler == null, e.g. TakeLast(source, 5, (IAsyncScheduler)null).
Common situations: Refactoring from the TakeLast(source, count) overload and adding a scheduler argument that is still null; a scheduler variable resolved from DI/config that returned null; conditional scheduler selection leaving the variable unset.
Related errors
- clock
- threadFactory (Parameter 'threadFactory')
- action (Parameter 'action')
- comparer (Parameter 'comparer')
- scheduler (Parameter 'scheduler')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/46bc91f8b006abb6.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/TakeLast.cs:46
count,
static async (source, count, observer) =>
{
var (sink, drain) = AsyncObserver.TakeLast(observer, count);
var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, drain);
});
}
public static IAsyncObservable<TSource> TakeLast<TSource>(this IAsyncObservable<TSource> source, int count, IAsyncScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
if (count == 0)
{
return Empty<TSource>();
}
return CreateAsyncObservable<TSource>.From(
source,
(count, scheduler),
static async (source, state, observer) =>
{
var (sink, drain) = AsyncObserver.TakeLast(observer, state.count, state.scheduler);
var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, drain);
});
}View on GitHub (pinned to 94b5d5ab91)