App-vNext/Polly · error · ArgumentOutOfRangeException

Invalid delay specified.

Error message

Invalid delay specified.

What it means

CancellationTokenSourcePool.Get(TimeSpan delay) rejects any delay that is <= TimeSpan.Zero unless it equals Timeout.InfiniteTimeSpan. The pool underlies timeout/hedging/retry delay scheduling; a non-positive finite delay would create an already-cancelled or invalid token source, so it is rejected up front with ArgumentOutOfRangeException.

Source

Thrown at src/Polly.Core/Utils/CancellationTokenSourcePool.cs:32

        return new PooledCancellationTokenSourcePool(timeProvider);
#elif NET6_0_OR_GREATER
        if (timeProvider == TimeProvider.System)
        {
            return PooledCancellationTokenSourcePool.SystemInstance;
        }

        return new DisposableCancellationTokenSourcePool(timeProvider);
#else
        return new DisposableCancellationTokenSourcePool(timeProvider);
#endif
    }

    public CancellationTokenSource Get(TimeSpan delay)
    {
        if (delay <= TimeSpan.Zero && delay != System.Threading.Timeout.InfiniteTimeSpan)
        {
            throw new ArgumentOutOfRangeException(nameof(delay), delay, "Invalid delay specified.");
        }

        return GetCore(delay);
    }

    protected abstract CancellationTokenSource GetCore(TimeSpan delay);

    public abstract void Return(CancellationTokenSource source);

    protected static bool IsCancellable(TimeSpan delay) => delay != System.Threading.Timeout.InfiniteTimeSpan;
}

View on GitHub (pinned to d0e46bdb1e)

Solutions

  1. Ensure all delay arguments are positive or Timeout.InfiniteTimeSpan before scheduling.
  2. Configure TimeoutStrategyOptions.Timeout / RetryStrategyOptions.BaseDelay to a positive value (or InfiniteTimeSpan to disable).
  3. Guard computed delays: if (delay < TimeSpan.Zero) delay = Timeout.InfiniteTimeSpan; before use.

Example fix

// before
options.Timeout = TimeSpan.Zero; // surfaces through the pool

// after
options.Timeout = TimeSpan.FromSeconds(30);
Defensive patterns

Strategy: validation

Validate before calling

static TimeSpan SafeDelay(TimeSpan d) =>
    d <= TimeSpan.Zero && d != System.Threading.Timeout.InfiniteTimeSpan
        ? throw new ArgumentOutOfRangeException(nameof(d)) : d;
// call SafeDelay(delay) before scheduling

Prevention

When it happens

Trigger: Passing TimeSpan.Zero, a negative TimeSpan, or default(TimeSpan) to Get(). InfiniteTimeSpan is the only allowed non-positive value. Normally strategy options validate their delays first; this guards the internal pool entry point.

Common situations: A custom strategy or fork that calls the pool directly with an unvalidated delay; misconfigured TimeoutStrategyOptions.Timeout = TimeSpan.Zero or negative; arithmetic that underflows a delay (e.g. maxDelay minus a larger elapsed).

Related errors


AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13). Data as JSON: /api/errors/f360467c86d39069. Report an issue: GitHub.