App-vNext/Polly · error · ArgumentOutOfRangeException
Value must be greater than zero.
Error message
Value must be greater than zero.
What it means
Thrown by the legacy generic CircuitBreaker<TResult> syntax when 'handledEventsAllowedBeforeBreaking' is <= 0. This is the result-handling equivalent of the non-generic breaker: it counts both handled exceptions and handled results before opening. The ArgumentOutOfRangeException is raised at policy construction.
Source
Thrown at src/Polly/CircuitBreaker/CircuitBreakerTResultSyntax.cs:188
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="policyBuilder">The policy builder.</param>
/// <param name="handledEventsAllowedBeforeBreaking">The number of exceptions or handled results that are allowed before opening the circuit.</param>
/// <param name="durationOfBreak">The duration the circuit will stay open before resetting.</param>
/// <param name="onBreak">The action to call when the circuit transitions to an <see cref="CircuitState.Open"/> state.</param>
/// <param name="onReset">The action to call when the circuit resets to a <see cref="CircuitState.Closed"/> state.</param>
/// <param name="onHalfOpen">The action to call when the circuit transitions to <see cref="CircuitState.HalfOpen"/> state, ready to try action executions again. </param>
/// <returns>The policy instance.</returns>
/// <remarks>(see "Release It!" by Michael T. Nygard fi).</remarks>
/// <exception cref="ArgumentOutOfRangeException">handledEventsAllowedBeforeBreaking;Value must be greater than zero.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="onBreak"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="onReset"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="onHalfOpen"/> is <see langword="null"/>.</exception>
public static CircuitBreakerPolicy<TResult> CircuitBreaker<TResult>(this PolicyBuilder<TResult> policyBuilder, int handledEventsAllowedBeforeBreaking, TimeSpan durationOfBreak, Action<DelegateResult<TResult>, CircuitState, TimeSpan, Context> onBreak, Action<Context> onReset, Action onHalfOpen)
{
if (handledEventsAllowedBeforeBreaking <= 0)
{
throw new ArgumentOutOfRangeException(nameof(handledEventsAllowedBeforeBreaking), "Value must be greater than zero.");
}
if (durationOfBreak < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(durationOfBreak), "Value must be greater than zero.");
}
if (onBreak == null)
{
throw new ArgumentNullException(nameof(onBreak));
}
if (onReset == null)
{
throw new ArgumentNullException(nameof(onReset));
}
if (onHalfOpen == null)View on GitHub (pinned to d0e46bdb1e)
Solutions
- Pass handledEventsAllowedBeforeBreaking >= 1.
- Validate/clamp the sourced value before building: var threshold = config.GetValue<int?>("Breaker:Threshold") ?? 5;.
- Confirm the parameter refers to handled events (results OR exceptions), not retries.
Example fix
// before
var policy = Policy<Result>
.Handle<HttpException>()
.OrResult(r => r.IsFailure)
.CircuitBreaker(0, TimeSpan.FromSeconds(30), onBreak, onReset, onHalfOpen);
// after
var threshold = config.GetValue<int?>("Breaker:Threshold") ?? 5;
var policy = Policy<Result>
.Handle<HttpException>()
.OrResult(r => r.IsFailure)
.CircuitBreaker(threshold, TimeSpan.FromSeconds(30), onBreak, onReset, onHalfOpen); Defensive patterns
Strategy: validation
Validate before calling
if (handledEventsAllowedBeforeBreaking <= 0) throw new ArgumentOutOfRangeException(nameof(handledEventsAllowedBeforeBreaking)); var policy = Policy<TResult>.Handle<X>().CircuitBreaker(handledEventsAllowedBeforeBreaking, durationOfBreak, ...);
Type guard
static int NormalizeThreshold(int v) => v <= 0 ? 1 : v;
Try / catch
try { var policy = builder.CircuitBreaker(n, ts, ...); } catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "handledEventsAllowedBeforeBreaking") { /* surface config error */ throw; } Prevention
- Validate thresholds at app startup from IConfiguration and fail fast.
- Document that the count covers both handled results and exceptions.
- Unit-test the builder with value=1 to lock the minimum.
When it happens
Trigger: Calling Policy<TResult>.Handle<...>().CircuitBreaker(handledEventsAllowedBeforeBreaking, durationOfBreak, onBreak, onReset, onHalfOpen) with handledEventsAllowedBeforeBreaking <= 0. Often hit when a threshold read from config is 0 or unset.
Common situations: Binding the threshold from IConfiguration with a missing key (resolves to 0); sharing a constant with a no-op policy that intentionally uses 0; misunderstanding that the count covers both faulted results and exceptions.
Related errors
- Value must be greater than zero.
- Value must be less than or equal to one.
- Value must be greater than one.
- Value must be greater than zero.
- Value must be less than or equal to one.
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/110c5cafaef44db8.
Report an issue: GitHub.