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 'time')

What it means

AdvanceTo moves the virtual clock forward to an absolute time, running all due work. If the requested time compares earlier than the current Clock (Comparer.Compare(time, Clock) < 0), time would run backwards, which virtual time cannot do, so ArgumentOutOfRangeException is thrown.

Solutions

  1. Pass a time >= scheduler.Clock; clamp with Math.Max(time, scheduler.Clock) if monotonicity is uncertain.
  2. Use GetNow()/scheduler.Clock as the reference instead of a stale stored value.
  3. Reorder test steps so AdvanceTo targets increase monotonically, or use a fresh scheduler instance.

Example fix

// before
scheduler.AdvanceTo(0); // Clock already at 100
// after
scheduler.AdvanceTo(Math.Max(0, scheduler.Clock));
Defensive patterns

Strategy: validation

Validate before calling

if (scheduler.Comparer.Compare(time, scheduler.Clock) < 0)
    throw new ArgumentOutOfRangeException(nameof(time), "time is before the current scheduler clock");

Type guard

bool CanAdvanceTo<TAbsolute>(VirtualTimeSchedulerBase<TAbsolute, TRelative> s, TAbsolute t) where TAbsolute : IComparable<TAbsolute> => s.Comparer.Compare(t, s.Clock) >= 0;

Try / catch

try { scheduler.AdvanceTo(time); } catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "time") { /* clamp or use scheduler.Clock instead */ }

Prevention

When it happens

Trigger: Calling AdvanceTo(t) where t < scheduler.Clock, e.g. calling AdvanceTo(0) after the clock already advanced, or passing a time captured before earlier AdvanceTo/AdvanceBy calls.

Common situations: Test sequences where steps are reordered or times are hardcoded and overlap; reusing a stale timestamp variable across test cases; mixing AdvanceTo with an already-advanced TestScheduler.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Concurrency/VirtualTimeScheduler.cs:208

        /// Stops the virtual time scheduler.
        /// </summary>
        public void Stop()
        {
            IsEnabled = false;
        }

        /// <summary>
        /// Advances the scheduler's clock to the specified time, running all work till that point.
        /// </summary>
        /// <param name="time">Absolute time to advance the scheduler's clock to.</param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="time"/> is in the past.</exception>
        /// <exception cref="InvalidOperationException">The scheduler is already running. VirtualTimeScheduler doesn't support running nested work dispatch loops. To simulate time slippage while running work on the scheduler, use <see cref="Sleep"/>.</exception>
        public void AdvanceTo(TAbsolute time)
        {
            var dueToClock = Comparer.Compare(time, Clock);
            if (dueToClock < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(time));
            }

            if (dueToClock == 0)
            {
                return;
            }

            if (!IsEnabled)
            {
                IsEnabled = true;
                do
                {
                    var next = GetNext();
                    if (next != null && Comparer.Compare(next.DueTime, time) <= 0)
                    {
                        if (Comparer.Compare(next.DueTime, Clock) > 0)
                        {
                            Clock = next.DueTime;

View on GitHub (pinned to 94b5d5ab91)