dotnet/reactive · error · ArgumentOutOfRangeException

Specified argument was out of the range of valid values. (Pa

Error message

Specified argument was out of the range of valid values. (Parameter 'window')

What it means

This ArgumentOutOfRangeException is thrown by the Replay<TSource>(source, TimeSpan window) operator when a negative replay window is passed. System.Reactive.Async requires window >= TimeSpan.Zero because the SequentialReplayAsyncSubject replays only items observed within the trailing window; a negative duration is meaningless. The throw is an eager, fail-fast argument validation performed before any subscription happens.

Solutions

  1. Inspect the TimeSpan value passed as 'window' and ensure it is >= TimeSpan.Zero before calling Replay
  2. Fix the computation producing the window (e.g. clamp with TimeSpan.FromTicks(Math.Max(0, diff.Ticks)))
  3. Validate configuration values for negative durations at startup and fail with a clear message

Example fix

// before
var window = endTime - startTime;
var replayed = source.Replay(window);
// after
var window = endTime - startTime;
if (window < TimeSpan.Zero) window = TimeSpan.Zero;
var replayed = source.Replay(window);
Defensive patterns

Strategy: validation

Validate before calling

if (window < TimeSpan.Zero)
    throw new ArgumentOutOfRangeException(nameof(window), "Replay window must be non-negative.");
var replayed = source.Replay(window);

Type guard

static bool IsValidReplayWindow(TimeSpan window) => window >= TimeSpan.Zero;

Try / catch

try
{
    var replayed = source.Replay(window);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "window")
{
    // fall back to zero window or log configuration error
}

Prevention

When it happens

Trigger: Calling Observable.Replay(source, TimeSpan.FromSeconds(-1)) or any Replay overload where the window TimeSpan was computed to a negative value (e.g. subtracting timestamps out of order, or a negative config value passed through).

Common situations: Reading a replay window from configuration where the value is negative or a negative Duration was computed from misordered timestamps (endTime - startTime with startTime > endTime); unit tests probing invalid inputs.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/fed927e792b9fc2c. Report an issue: GitHub.

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Replay.cs:60

        public static IConnectableAsyncObservable<TSource> Replay<TSource>(this IAsyncObservable<TSource> source, int bufferSize, IAsyncScheduler scheduler)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (bufferSize < 0)
                throw new ArgumentOutOfRangeException(nameof(bufferSize));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Multicast(source, new SequentialReplayAsyncSubject<TSource>(bufferSize, scheduler));
        }

        public static IConnectableAsyncObservable<TSource> Replay<TSource>(this IAsyncObservable<TSource> source, TimeSpan window)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (window < TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(window));

            return Multicast(source, new SequentialReplayAsyncSubject<TSource>(window));
        }

        public static IConnectableAsyncObservable<TSource> Replay<TSource>(this IAsyncObservable<TSource> source, TimeSpan window, IAsyncScheduler scheduler)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (window < TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(window));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Multicast(source, new SequentialReplayAsyncSubject<TSource>(window, scheduler));
        }

        public static IConnectableAsyncObservable<TSource> Replay<TSource>(this IAsyncObservable<TSource> source, int bufferSize, TimeSpan window)
        {

View on GitHub (pinned to 94b5d5ab91)