dotnet/reactive · error · ArgumentOutOfRangeException
duration
Error message
duration
What it means
TakeLast(source, duration) throws ArgumentOutOfRangeException("duration") when the TimeSpan is negative. A negative duration is meaningless for a 'take the last items within this window' operator, so the library rejects it up front with the parameter name.
Solutions
- Clamp or validate the duration to TimeSpan.Zero or greater before calling
- Use TimeSpan.Zero explicitly when the intent is an empty result (the operator returns Empty for zero)
- Fix the computation producing the negative TimeSpan (swapped operands, wrong clock)
Example fix
// before var result = source.TakeLast(end - start); // end < start -> negative // after var duration = end > start ? end - start : TimeSpan.Zero; var result = source.TakeLast(duration);
Defensive patterns
Strategy: validation
Validate before calling
if (duration < TimeSpan.Zero) duration = TimeSpan.Zero; var result = source.TakeLast(duration);
Type guard
bool IsValidDuration(TimeSpan d) => d >= TimeSpan.Zero;
Try / catch
try { var r = source.TakeLast(duration); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "duration") { var r = source.TakeLast(TimeSpan.Zero); } Prevention
- Validate user/config-supplied durations for sign at parse time
- Use Math.Max(TimeSpan.Zero, computed) on derived windows
- Keep a single helper for building TimeSpans from config
When it happens
Trigger: Calling source.TakeLast(TimeSpan.FromMilliseconds(-1)) or passing a duration computed from clock differences that came out negative.
Common situations: Computing a window as endTime - startTime where the values were swapped or the clock was non-monotonic; user/config-supplied durations parsed without sign validation; arithmetic on subtracted TimeSpans underflowing intent.
Related errors
- ArgumentOutOfRangeException
- ArgumentOutOfRangeException: window
- clock
- Delay cannot be less than zero
- duration
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/98822f1125721b2a.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/TakeLast.cs:71
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);
});
}
public static IAsyncObservable<TSource> TakeLast<TSource>(this IAsyncObservable<TSource> source, TimeSpan duration)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (duration < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(duration));
if (duration == TimeSpan.Zero)
{
return Empty<TSource>();
}
return CreateAsyncObservable<TSource>.From(
source,
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);
});
}View on GitHub (pinned to 94b5d5ab91)