dotnet/reactive · error · ArgumentOutOfRangeException
throw new ArgumentOutOfRangeException(nameof(period));
Error message
throw new ArgumentOutOfRangeException(nameof(period));
What it means
Observable.Timer(TimeSpan dueTime, TimeSpan period) throws ArgumentOutOfRangeException when period is negative, because a repeating timer cannot have a negative interval between emissions. TimeSpan.Zero is allowed (indefinite repetitions as fast as the scheduler permits), but any value below Zero is rejected eagerly.
Solutions
- Pass a non-negative TimeSpan for period (use TimeSpan.Zero for continuous repetitions)
- Validate or clamp the configured interval: if (period < TimeSpan.Zero) period = TimeSpan.Zero
- Fix the calculation producing the negative TimeSpan (check operand order in subtractions)
Example fix
// before var period = TimeSpan.FromSeconds(target) - TimeSpan.FromSeconds(current); // can be negative var timer = Observable.Timer(dueTime, period); // after var period = TimeSpan.FromSeconds(Math.Max(0, target - current)); var timer = Observable.Timer(dueTime, period);
Defensive patterns
Strategy: validation
Validate before calling
if (period < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(period));
var timer = Observable.Timer(dueTime, period); Type guard
bool isValid = period >= TimeSpan.Zero;
Try / catch
try
{
timer = Observable.Timer(dueTime, period);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "period")
{
timer = Observable.Timer(dueTime, TimeSpan.Zero);
} Prevention
- Clamp computed intervals with Math.Max(TimeSpan.Zero, interval)
- Validate configured durations at load time, rejecting negatives early
- Watch timestamp subtraction order — (a - b) goes negative when a < b
When it happens
Trigger: Calling Observable.Timer(dueTime, TimeSpan.FromMilliseconds(-1)) or computing the period from an expression that yields a negative TimeSpan (e.g. subtracting timestamps in the wrong order, or a config value parsed with a negative sign).
Common situations: Polling intervals read from configuration where the value is negative or the subtraction of due dates inverts order; unit tests using negative delays; arithmetic like (a - b) where a < b.
Related errors
- period (Parameter 'period')
- Specified argument was out of the range of valid values…
- Specified argument was out of the range of valid values…
- Specified argument was out of the range of valid values…
- period
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/4905d29b30bda9a4.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs:2046
/// <param name="dueTime">Absolute time at which to produce the value. If this value is less than or equal to DateTimeOffset.UtcNow, the timer will fire as soon as possible.</param>
/// <returns>An observable sequence that produces a value at due time.</returns>
public static IObservable<long> Timer(DateTimeOffset dueTime)
{
return s_impl.Timer(dueTime);
}
/// <summary>
/// Returns an observable sequence that periodically produces a value after the specified initial relative due time has elapsed.
/// </summary>
/// <param name="dueTime">Relative time at which to produce the first value. If this value is less than or equal to TimeSpan.Zero, the timer will fire as soon as possible.</param>
/// <param name="period">Period to produce subsequent values. If this value is equal to TimeSpan.Zero, the timer will recur as fast as possible.</param>
/// <returns>An observable sequence that produces a value after due time has elapsed and then after each period.</returns>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than TimeSpan.Zero.</exception>
public static IObservable<long> Timer(TimeSpan dueTime, TimeSpan period)
{
if (period < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(period));
}
return s_impl.Timer(dueTime, period);
}
/// <summary>
/// Returns an observable sequence that periodically produces a value starting at the specified initial absolute due time.
/// </summary>
/// <param name="dueTime">Absolute time at which to produce the first value. If this value is less than or equal to DateTimeOffset.UtcNow, the timer will fire as soon as possible.</param>
/// <param name="period">Period to produce subsequent values. If this value is equal to TimeSpan.Zero, the timer will recur as fast as possible.</param>
/// <returns>An observable sequence that produces a value at due time and then after each period.</returns>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="period"/> is less than TimeSpan.Zero.</exception>
public static IObservable<long> Timer(DateTimeOffset dueTime, TimeSpan period)
{
if (period < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(period));
}View on GitHub (pinned to 94b5d5ab91)