dotnet/reactive · error · ArgumentOutOfRangeException
ArgumentOutOfRangeException
Error message
ArgumentOutOfRangeException
What it means
The Timer(TimeSpan, TimeSpan) overload requires a non-negative period. System.Reactive.Async validates the period eagerly and throws ArgumentOutOfRangeException when period < TimeSpan.Zero, since a repeating timer cannot tick at a negative interval.
Solutions
- Ensure the period argument is >= TimeSpan.Zero before calling Timer.
- If the period is computed, clamp it: Math.Max(TimeSpan.Zero, computedPeriod).
- Validate/normalize any configuration value feeding the period.
Example fix
// before var timer = AsyncObservable.Timer(dueTime, end - start); // end < start => negative // after var period = end > start ? end - start : TimeSpan.Zero; var timer = AsyncObservable.Timer(dueTime, period);
Defensive patterns
Strategy: validation
Validate before calling
if (period < TimeSpan.Zero)
throw new InvalidOperationException("Timer period must be non-negative");
var timer = AsyncObservable.Timer(dueTime, period); Type guard
bool IsValidPeriod(TimeSpan p) => p >= TimeSpan.Zero;
Try / catch
try
{
var timer = AsyncObservable.Timer(dueTime, period);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "period")
{
timer = AsyncObservable.Timer(dueTime, TimeSpan.Zero);
} Prevention
- Clamp computed durations with TimeSpan.Max or explicit comparison.
- Validate interval config values at load time.
- Check subtraction order when deriving periods from timestamps.
When it happens
Trigger: Calling AsyncObservable.Timer(dueTime, TimeSpan.FromSeconds(-1)) — any TimeSpan period whose value is negative.
Common situations: Period computed by subtracting timestamps (later - earlier reversed) or parsed from a user-supplied configuration value that is negative; sign errors in constants.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/e05ea20117b3bb79.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Timer.cs:41
}
public static IAsyncObservable<long> Timer(DateTimeOffset dueTime)
{
return Create<long>(observer => AsyncObserver.Timer(observer, dueTime));
}
public static IAsyncObservable<long> Timer(DateTimeOffset dueTime, IAsyncScheduler scheduler)
{
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return Create<long>(observer => AsyncObserver.Timer(observer, dueTime, scheduler));
}
public static IAsyncObservable<long> Timer(TimeSpan dueTime, TimeSpan period)
{
if (period < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(period));
return Create<long>(observer => AsyncObserver.Timer(observer, dueTime, period));
}
public static IAsyncObservable<long> Timer(TimeSpan dueTime, TimeSpan period, IAsyncScheduler scheduler)
{
if (period < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(period));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return Create<long>(observer => AsyncObserver.Timer(observer, dueTime, period, scheduler));
}
public static IAsyncObservable<long> Timer(DateTimeOffset dueTime, TimeSpan period)
{
if (period < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(period));View on GitHub (pinned to 94b5d5ab91)