dotnet/reactive · error · ArgumentOutOfRangeException

Specified argument was out of range of valid values…

Error message

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

What it means

The window parameter of Replay(source, bufferSize, window, scheduler) defines the time span for which notifications are replayed and must not be negative. A negative TimeSpan is rejected eagerly with ArgumentOutOfRangeException (message parameter 'window').

Solutions

  1. Pass a non-negative TimeSpan (use TimeSpan.Zero for no window trimming)
  2. Apply TimeSpan.FromTicks(Math.Abs(ts.Ticks)) if the value is derived from a difference
  3. Validate the configured duration at startup

Example fix

// before
var conn = source.Replay(10, TimeSpan.FromSeconds(-5), scheduler);
// after
var conn = source.Replay(10, TimeSpan.FromSeconds(5), scheduler);
Defensive patterns

Strategy: validation

Validate before calling

if (window < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(window));

Type guard

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

Try / catch

try { var conn = src.Replay(size, window, scheduler); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "window") { window = TimeSpan.Zero; /* retry */ }

Prevention

When it happens

Trigger: Calling source.Replay(bufferSize, negativeTimeSpan, scheduler), e.g. TimeSpan.FromSeconds(-5) or a TimeSpan computed by subtraction (later - earlier) that came out negative.

Common situations: Duration loaded from config where units were misread (milliseconds vs seconds) yielding a negative value; clock/timestamp subtraction without Math.Abs; refactored constant with a stray minus sign.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Binding.cs:881

        /// <exception cref="ArgumentOutOfRangeException"><paramref name="bufferSize"/> is less than zero.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="window"/> is less than TimeSpan.Zero.</exception>
        /// <remarks>Subscribers will receive all the notifications of the source subject to the specified replay buffer trimming policy.</remarks>
        /// <seealso cref="ReplaySubject{T}"/>
        public static IConnectableObservable<TSource> Replay<TSource>(this IObservable<TSource> source, int bufferSize, TimeSpan window, IScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            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 s_impl.Replay(source, bufferSize, window, scheduler);
        }

        /// <summary>
        /// Returns an observable sequence that is the result of invoking the selector on a connectable observable sequence that shares a single subscription to the underlying sequence replaying notifications subject to a maximum time length and element count for the replay buffer.
        /// This operator is a specialization of Multicast using a <see cref="ReplaySubject{T}"/>.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence.</typeparam>
        /// <param name="source">Source sequence whose elements will be multicasted through a single shared subscription.</param>
        /// <param name="selector">Selector function which can use the multicasted source sequence as many times as needed, without causing multiple subscriptions to the source sequence. Subscribers to the given source will receive all the notifications of the source subject to the specified replay buffer trimming policy.</param>

View on GitHub (pinned to 94b5d5ab91)