dotnet/reactive · error · ArgumentNullException
clock
Error message
clock
What it means
TakeLast(source, duration, clock) throws ArgumentNullException("clock") because this overload requires an explicit IClock to define 'now' for the time window. Null is rejected eagerly with the parameter name instead of failing during subscription.
Solutions
- Pass a concrete IClock (system clock or test/virtual clock) instance
- Use the TakeLast(source, duration) overload when the default clock suffices
- Fix the clock provider/DI registration so it yields a non-null instance
Example fix
// before var result = source.TakeLast(TimeSpan.FromSeconds(5), (IClock)null); // after var result = source.TakeLast(TimeSpan.FromSeconds(5), clock); // injected IClock // or: var result = source.TakeLast(TimeSpan.FromSeconds(5));
Defensive patterns
Strategy: validation
Validate before calling
if (clock is null) throw new InvalidOperationException("IClock must be resolved before calling TakeLast");
var result = source.TakeLast(duration, clock); Type guard
bool HasClock(IClock? c) => c is not null;
Try / catch
try { var r = source.TakeLast(duration, clock); }
catch (ArgumentNullException ex) when (ex.ParamName == "clock") { var r = source.TakeLast(duration); } Prevention
- Register IClock in DI at application startup
- In tests, initialize the virtual clock before building queries
- Use the default-clock overload when a custom clock adds no value
When it happens
Trigger: Calling TakeLast(source, duration, (IClock)null), or passing a clock obtained from an accessor that returned null.
Common situations: Test code forgetting to supply a fake/test clock; DI container not registered for IClock; refactoring from the two-argument overload and adding a null clock placeholder.
Related errors
- scheduler
- Value cannot be null. (Parameter 'onNextAsync')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'second')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/074f86ec8b4d2116.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/TakeLast.cs:98
duration,
static async (source, duration, observer) =>
{
var (sink, drain) = AsyncObserver.TakeLast(observer, duration);
var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, drain);
});
}
public static IAsyncObservable<TSource> TakeLast<TSource>(this IAsyncObservable<TSource> source, TimeSpan duration, IClock clock)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (duration < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(duration));
if (clock == null)
throw new ArgumentNullException(nameof(clock));
if (duration == TimeSpan.Zero)
{
return Empty<TSource>();
}
return CreateAsyncObservable<TSource>.From(
source,
(duration, clock),
static async (source, state, observer) =>
{
var (sink, drain) = AsyncObserver.TakeLast(observer, state.duration, state.clock);
var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, drain);
});
}View on GitHub (pinned to 94b5d5ab91)