dotnet/reactive · error · ArgumentOutOfRangeException

throw new ArgumentOutOfRangeException(nameof(dueTime));

Error message

throw new ArgumentOutOfRangeException(nameof(dueTime));

What it means

Observable.Delay throws ArgumentOutOfRangeException when dueTime is negative. dueTime is a scheduler due time used to shift emissions into the future; negative durations are meaningless for Delay (unlike Buffer, Delay here rejects only negative values). The check is performed eagerly at the call site.

Solutions

  1. Pass a non-negative TimeSpan, e.g. TimeSpan.FromSeconds(5)
  2. Clamp computed delays: if (delay < TimeSpan.Zero) delay = TimeSpan.Zero;
  3. Validate delay configuration at startup before it reaches the Rx pipeline

Example fix

// before
var delay = deadline - DateTime.Now; // may be negative
var delayed = source.Delay(delay);
// after
var delay = deadline - DateTime.Now;
if (delay < TimeSpan.Zero) delay = TimeSpan.Zero;
var delayed = source.Delay(delay);
Defensive patterns

Strategy: validation

Validate before calling

if (dueTime < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(dueTime));
// or clamp: dueTime = dueTime < TimeSpan.Zero ? TimeSpan.Zero : dueTime;

Try / catch

try { var d = source.Delay(dueTime); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "dueTime") { dueTime = TimeSpan.Zero; /* retry */ }

Prevention

When it happens

Trigger: Calling Observable.Delay(source, dueTime) with dueTime < TimeSpan.Zero, e.g. TimeSpan.FromSeconds(-1), a negative configured delay, or a duration computed from clock values in the wrong order.

Common situations: Delay/timeout settings read from config as negative values; subtracting timestamps with the operands swapped; sign mistakes in dynamic delay computations (e.g. remaining time after a deadline passed).

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs:291

        /// </para>
        /// <para>
        /// Observer callbacks for the resulting sequence will be run on the default scheduler. This effect is similar to using ObserveOn.
        /// </para>
        /// <para>
        /// Exceptions signaled by the source sequence through an OnError callback are forwarded immediately to the result sequence. Any OnNext notifications that were in the queue at the point of the OnError callback will be dropped.
        /// In order to delay error propagation, consider using the <see cref="Materialize">Observable.Materialize</see> and <see cref="Dematerialize">Observable.Dematerialize</see> operators, or use <see cref="Observable.DelaySubscription{T}(IObservable{T}, TimeSpan)">DelaySubscription</see>.
        /// </para>
        /// </remarks>
        public static IObservable<TSource> Delay<TSource>(this IObservable<TSource> source, TimeSpan dueTime)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (dueTime < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(dueTime));
            }

            return s_impl.Delay(source, dueTime);
        }

        /// <summary>
        /// Time shifts the observable sequence by the specified relative time duration, using the specified scheduler to run timers.
        /// The relative time intervals between the values are preserved.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source sequence to delay values for.</param>
        /// <param name="dueTime">Relative time by which to shift the observable sequence. If this value is equal to TimeSpan.Zero, the scheduler will dispatch observer callbacks as soon as possible.</param>
        /// <param name="scheduler">Scheduler to run the delay timers on.</param>
        /// <returns>Time-shifted sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="scheduler"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="dueTime"/> is less than TimeSpan.Zero.</exception>
        /// <remarks>
        /// <para>

View on GitHub (pinned to 94b5d5ab91)