App-vNext/Polly · error · ArgumentOutOfRangeException
Value must be greater than or equal to zero.
Error message
Value must be greater than or equal to zero.
What it means
Thrown by RetryAsync<TResult> when retryCount is negative (the guard is retryCount < 0). The message says 'Value must be greater than or equal to zero' — note the XML doc incorrectly says 'greater than zero', but zero retries (i.e. no retries) is actually permitted. This overload is the terminal context-aware async variant; it validates retryCount before onRetryAsync. A negative count has no semantic meaning for a retry policy.
Source
Thrown at src/Polly/Retry/AsyncRetryTResultSyntax.cs:161
#pragma warning restore 1998
}
/// <summary>
/// Builds an <see cref="AsyncRetryPolicy{TResult}"/> that will retry <paramref name="retryCount"/> times
/// calling <paramref name="onRetryAsync"/> on each retry with the handled exception or result, retry count and context data.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="policyBuilder">The policy builder.</param>
/// <param name="retryCount">The retry count.</param>
/// <param name="onRetryAsync">The action to call asynchronously on each retry.</param>
/// <returns>The policy instance.</returns>
/// <exception cref="ArgumentOutOfRangeException">retryCount;Value must be greater than zero.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="onRetryAsync"/> is <see langword="null"/>.</exception>
public static AsyncRetryPolicy<TResult> RetryAsync<TResult>(this PolicyBuilder<TResult> policyBuilder, int retryCount, Func<DelegateResult<TResult>, int, Context, Task> onRetryAsync)
{
if (retryCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(retryCount), "Value must be greater than or equal to zero.");
}
if (onRetryAsync == null)
{
throw new ArgumentNullException(nameof(onRetryAsync));
}
return new AsyncRetryPolicy<TResult>(
policyBuilder,
(outcome, _, i, ctx) => onRetryAsync(outcome, i, ctx),
retryCount);
}
/// <summary>
/// Builds an <see cref="AsyncRetryPolicy{TResult}" /> that will retry indefinitely until the action succeeds.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="policyBuilder">The policy builder.</param>View on GitHub (pinned to d0e46bdb1e)
Solutions
- Clamp the value before the call: Math.Max(0, retryCount).
- Validate config at startup and fail with a clear message if retryCount < 0.
- Note that 0 is valid (policy never retries); only negative throws.
Example fix
// before Policy.HandleResult<T>(IsHandled).RetryAsync(retryCountFromConfig, onRetryAsync); // after var retryCount = Math.Max(0, retryCountFromConfig); Policy.HandleResult<T>(IsHandled).RetryAsync(retryCount, onRetryAsync);
Defensive patterns
Strategy: validation
Validate before calling
if (retryCount < 0) throw new ArgumentOutOfRangeException(nameof(retryCount), "retryCount must be >= 0"); // safe retryCount is Math.Max(0, retryCount) if a default of 0 is acceptable
Type guard
static bool IsValidRetryCount(int count) => count >= 0;
Try / catch
try { Policy.HandleResult<T>(IsHandled).RetryAsync(retryCount, onRetryAsync); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == nameof(retryCount))
{ retryCount = 0; /* rebuild with a valid count */ } Prevention
- Validate config-sourced retry counts at startup and reject negative sentinels early.
- Clamp derived counts with Math.Max(0, value) when a 0-retry fallback is acceptable.
- Add a contract test that the configured retry count is non-negative across environments.
When it happens
Trigger: Passing a literal negative number, computing retryCount from config that defaulted to -1, or subtracting from a count and going below zero (e.g. retryCount - 1 when retryCount is 0).
Common situations: Config value missing and parsed to a sentinel like -1, arithmetic underflow in a derived count, or an environment-specific override that was never validated.
Related errors
- onRetry
- onRetryAsync
- The retry backoff type is not supported.
- 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/d4c6a8aad556c5db.
Report an issue: GitHub.