dotnet/reactive · error · ArgumentOutOfRangeException
Specified argument was out of the range of valid values…
Error message
Specified argument was out of the range of valid values. (Parameter 'timeSpan')
What it means
This ArgumentOutOfRangeException is thrown by the time-based Window helper when timeSpan is negative (less than TimeSpan.Zero). Zero is allowed (windows close immediately per tick semantics), but a negative duration has no meaning for a timer-based window. The check runs synchronously before any scheduling occurs.
Solutions
- Pass a non-negative TimeSpan such as TimeSpan.FromSeconds(5).
- Clamp: if (ts < TimeSpan.Zero) ts = TimeSpan.Zero; or throw your own validation error earlier.
- Fix the config/parser so durations are validated as non-negative at load time.
- Check any date/duration arithmetic producing the TimeSpan for reversed operands.
Example fix
// before var ts = end - start; // end earlier than start => negative var windows = source.Window(ts); // after var ts = end > start ? end - start : TimeSpan.Zero; var windows = source.Window(ts);
Defensive patterns
Strategy: validation
Validate before calling
if (timeSpan < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(timeSpan), timeSpan, "Window duration must be non-negative."); // or clamp: timeSpan = timeSpan < TimeSpan.Zero ? TimeSpan.Zero : timeSpan;
Type guard
bool IsValidDuration(TimeSpan ts) => ts >= TimeSpan.Zero;
Try / catch
try
{
var windows = source.Window(timeSpan);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "timeSpan")
{
timeSpan = DefaultWindowDuration; // e.g. TimeSpan.FromSeconds(1)
} Prevention
- Validate durations from configuration as non-negative at parse time.
- Check for reversed operands in end-start TimeSpan arithmetic.
- Represent durations with unsigned/validated types at your config boundary.
When it happens
Trigger: Calling Window(source, timeSpan) or the internal helper with a negative TimeSpan, e.g. a value read from config in milliseconds that was negative, or subtracting TimeSpans in the wrong order.
Common situations: Duration configuration parsed as a signed number; clock arithmetic (end - start with end < start); serialization of durations that lost sign constraints.
Related errors
- Specified argument was out of the range of valid values…
- Specified argument was out of the range of valid values…
- duration
- throw new ArgumentOutOfRangeException(nameof(dueTime));
- ArgumentOutOfRangeException
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/4b56e25617039927.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Window.cs:295
}
await observer.OnCompletedAsync().ConfigureAwait(false);
}
),
refCount
);
}
public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> Window<TSource>(IAsyncObserver<IAsyncObservable<TSource>> observer, IAsyncDisposable subscription, TimeSpan timeSpan) => Window(observer, subscription, timeSpan, TaskPoolAsyncScheduler.Default);
public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> Window<TSource>(IAsyncObserver<IAsyncObservable<TSource>> observer, IAsyncDisposable subscription, TimeSpan timeSpan, IAsyncScheduler scheduler)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (subscription == null)
throw new ArgumentNullException(nameof(subscription));
if (timeSpan < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(timeSpan));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
var gate = new AsyncGate();
var window = default(IAsyncSubject<TSource>);
var d = new CompositeAsyncDisposable();
var refCount = new RefCountAsyncDisposable(d);
async Task CreateWindowAsync()
{
window = new SequentialSimpleAsyncSubject<TSource>();
var wrapper = new WindowAsyncObservable<TSource>(window, refCount);
await observer.OnNextAsync(wrapper).ConfigureAwait(false);
}
View on GitHub (pinned to 94b5d5ab91)