App-vNext/Polly · error · ArgumentOutOfRangeException
timeout
Error message
timeout
What it means
Thrown by TimeoutAsync<TResult>(TimeSpan timeout, ...) (optimistic-only) when timeout <= TimeSpan.Zero. The guard rejects zero and negative spans; notably InfiniteTimeSpan is also rejected here even though other Polly surfaces accept it. Construction-time range check.
Source
Thrown at src/Polly/Timeout/AsyncTimeoutTResultSyntax.cs:165
TimeoutValidator.ValidateTimeSpanTimeout(timeout);
return TimeoutAsync<TResult>(_ => timeout, TimeoutStrategy.Optimistic, onTimeoutAsync);
}
/// <summary>
/// Builds an <see cref="AsyncPolicy{TResult}"/> that will wait asynchronously for a delegate to complete for a specified period of time. A <see cref="TimeoutRejectedException"/> will be thrown if the delegate does not complete within the configured timeout.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="timeout">The timeout.</param>
/// <param name="onTimeoutAsync">An action to call on timeout, passing the execution context, the timeout applied, the <see cref="Task"/> capturing the abandoned, timed-out action, and the captured <see cref="Exception"/>.
/// <remarks>The Task parameter will be null if the executed action responded cooperatively to cancellation before the policy timed it out.</remarks></param>
/// <returns>The policy instance.</returns>
/// <exception cref="ArgumentOutOfRangeException">timeout;Value must be greater than zero.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="onTimeoutAsync"/> is <see langword="null"/>.</exception>
public static AsyncTimeoutPolicy<TResult> TimeoutAsync<TResult>(TimeSpan timeout, Func<Context, TimeSpan, Task, Exception, Task> onTimeoutAsync)
{
if (timeout <= TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(timeout));
}
return TimeoutAsync<TResult>(_ => timeout, TimeoutStrategy.Optimistic, onTimeoutAsync);
}
/// <summary>
/// Builds an <see cref="AsyncPolicy{TResult}"/> that will wait asynchronously for a delegate to complete for a specified period of time. A <see cref="TimeoutRejectedException"/> will be thrown if the delegate does not complete within the configured timeout.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="timeout">The timeout.</param>
/// <param name="timeoutStrategy">The timeout strategy.</param>
/// <param name="onTimeoutAsync">An action to call on timeout, passing the execution context, the timeout applied, and a <see cref="Task"/> capturing the abandoned, timed-out action.
/// <remarks>The Task parameter will be null if the executed action responded cooperatively to cancellation before the policy timed it out.</remarks></param>
/// <returns>The policy instance.</returns>
/// <exception cref="ArgumentOutOfRangeException">timeout;Value must be a positive TimeSpan (or Timeout.InfiniteTimeSpan to indicate no timeout).</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="onTimeoutAsync"/> is <see langword="null"/>.</exception>
public static AsyncTimeoutPolicy<TResult> TimeoutAsync<TResult>(TimeSpan timeout, TimeoutStrategy timeoutStrategy, Func<Context, TimeSpan, Task, Task> onTimeoutAsync)
{View on GitHub (pinned to d0e46bdb1e)
Solutions
- Pass a strictly positive TimeSpan, e.g. TimeSpan.FromSeconds(30).
- If you genuinely need no timeout, omit the policy rather than passing InfiniteTimeSpan to this overload.
- Validate upstream: if (timeout <= TimeSpan.Zero) fail fast with a clear config error.
Example fix
// before Policy.TimeoutAsync<MyResult>(TimeSpan.Zero, onTimeoutAsync); Policy.TimeoutAsync<MyResult>(Timeout.InfiniteTimeSpan, onTimeoutAsync); // also throws // after Policy.TimeoutAsync<MyResult>(TimeSpan.FromSeconds(30), onTimeoutAsync);
Defensive patterns
Strategy: validation
Validate before calling
if (timeout <= TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(timeout), "must be > Zero; InfiniteTimeSpan not supported here"); var policy = Policy.TimeoutAsync<TResult>(timeout, onTimeoutAsync);
Type guard
static bool IsValidSpan(TimeSpan t) => t > TimeSpan.Zero;
Prevention
- Do not pass Timeout.InfiniteTimeSpan to this overload.
- Validate spans parsed from config before constructing the policy.
- Default(TimeSpan) is Zero — guard uninitialized struct fields.
When it happens
Trigger: Calling Policy.TimeoutAsync<TResult>(TimeSpan.Zero, onTimeoutAsync), a negative TimeSpan, or Timeout.InfiniteTimeSpan (which is negative). Misreading the doc — which mentions InfiniteTimeSpan only on the no-callback overload — leads developers to try it here.
Common situations: Passing default(TimeSpan) from an uninitialized struct; subtracting two DateTimes that yield negative; reading '00:00:00' from config; assuming InfiniteTimeSpan works on every overload.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- seconds
- onTimeoutAsync
- timeoutProvider
- Value must be greater than zero.
- Value must be greater than or equal to zero.
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/72c544f189aa2b66.
Report an issue: GitHub.