dotnet/reactive · error · ArgumentOutOfRangeException
throw new ArgumentOutOfRangeException(nameof(window));
Error message
throw new ArgumentOutOfRangeException(nameof(window));
What it means
The Replay(source, selector, bufferSize, window) operator validates the replay window and throws ArgumentOutOfRangeException when window is a negative TimeSpan. A negative expiration window for replayed items is meaningless, so the guard rejects it before constructing the SequentialReplayAsyncSubject.
Solutions
- Pass TimeSpan.Zero or a positive TimeSpan for the window.
- Clamp before calling: window = window < TimeSpan.Zero ? TimeSpan.Zero : window.
- Validate configured durations at load time (reject negatives with a clear message).
Example fix
// before var replayed = AsyncObservable.Replay(source, sel, 10, window: TimeSpan.FromSeconds(-5)); // after var replayed = AsyncObservable.Replay(source, sel, 10, window: TimeSpan.FromSeconds(5));
Defensive patterns
Strategy: validation
Validate before calling
if (window < TimeSpan.Zero) throw new ArgumentException("window must be non-negative", nameof(window)); Try / catch
try { var replayed = AsyncObservable.Replay(source, sel, bufferSize, window); } catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "window") { /* fall back to TimeSpan.Zero */ } Prevention
- Check duration arithmetic for reversed operands.
- Validate TimeSpan config values at load time.
- Use TimeSpan.Zero for 'no window'.
When it happens
Trigger: Calling AsyncObservable.Replay(source, selector, bufferSize, window) with a TimeSpan less than TimeSpan.Zero, e.g. a window parsed from a negative configured value or computed as an earlier timestamp minus a later one.
Common situations: Timespan parsed from config where the user entered '-5' intending seconds of magnitude; computing a duration by subtracting DateTime/Stopwatch values in the wrong order; unit tests passing TimeSpan.MinValue.
Related errors
- Value cannot be null. (Parameter 'timeShift')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'subscription')
- throw new ArgumentOutOfRangeException(nameof(bufferSize));
- throw new ArgumentNullException(nameof(source));
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/0f227b9434e3c323.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Replay.cs:290
throw new ArgumentNullException(nameof(selector));
if (window < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(window));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return Multicast(source, () => new ValueTask<IAsyncSubject<TSource, TSource>>(new SequentialReplayAsyncSubject<TSource>(window, scheduler)), selector);
}
public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, ValueTask<IAsyncObservable<TResult>>> selector, int bufferSize, TimeSpan window)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (window < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(window));
return Multicast(source, () => new ValueTask<IAsyncSubject<TSource, TSource>>(new SequentialReplayAsyncSubject<TSource>(bufferSize, window)), selector);
}
public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, ValueTask<IAsyncObservable<TResult>>> selector, int bufferSize, TimeSpan window, IAsyncScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (window < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(window));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return Multicast(source, () => new ValueTask<IAsyncSubject<TSource, TSource>>(new SequentialReplayAsyncSubject<TSource>(bufferSize, window, scheduler)), selector);View on GitHub (pinned to 94b5d5ab91)