App-vNext/Polly · error · ArgumentNullException
sleepDurationProvider
Error message
sleepDurationProvider
What it means
Thrown by the legacy Polly v7 synchronous WaitAndRetry API when the sleepDurationProvider (Func<int, TimeSpan>) is null for the canonical overload. The provider is invoked once per retry to build the sleep-duration sequence, so a null provider would NRE during Enumerable.Select; Polly validates it at construction.
Source
Thrown at src/Polly/Retry/RetrySyntax.cs:270
/// the current retry number (1 for first retry, 2 for second etc).
/// </summary>
/// <param name="policyBuilder">The policy builder.</param>
/// <param name="retryCount">The retry count.</param>
/// <param name="sleepDurationProvider">The function that provides the duration to wait for a particular retry attempt.</param>
/// <param name="onRetry">The action to call on each retry.</param>
/// <returns>The policy instance.</returns>
/// <exception cref="ArgumentOutOfRangeException">retryCount;Value must be greater than or equal to zero.</exception>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="sleepDurationProvider"/> or <paramref name="onRetry"/> is <see langword="null"/>.</exception>
public static RetryPolicy WaitAndRetry(this PolicyBuilder policyBuilder, int retryCount, Func<int, TimeSpan> sleepDurationProvider, Action<Exception, TimeSpan, int, Context> onRetry)
{
if (retryCount < 0)
{
throw new ArgumentOutOfRangeException(nameof(retryCount), "Value must be greater than or equal to zero.");
}
if (sleepDurationProvider == null)
{
throw new ArgumentNullException(nameof(sleepDurationProvider));
}
if (onRetry == null)
{
throw new ArgumentNullException(nameof(onRetry));
}
var sleepDurations = Enumerable.Range(1, retryCount)
.Select(sleepDurationProvider);
return new RetryPolicy(
policyBuilder,
onRetry,
retryCount,
sleepDurationsEnumerable: sleepDurations);
}
/// <summary>View on GitHub (pinned to d0e46bdb1e)
Solutions
- Supply a non-null Func<int, TimeSpan>, e.g. attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)).
- Use a named helper (Polly Backoff) or a constant provider instead of null.
- Validate the provider is non-null before building the policy.
Example fix
// before
var policy = Policy.Handle<HttpRequestException>().WaitAndRetry(3, null, (ex, d, i, ctx) => Log(ex, d, i, ctx));
// after
var policy = Policy.Handle<HttpRequestException>().WaitAndRetry(3,
attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
(ex, d, i, ctx) => Log(ex, d, i, ctx)); Defensive patterns
Strategy: validation
Validate before calling
if (sleepDurationProvider is null)
throw new InvalidOperationException("sleepDurationProvider is required.");
var policy = Policy.Handle<TException>(pred).WaitAndRetry(retryCount, sleepDurationProvider, onRetry); Type guard
static bool IsValid(Func<int, TimeSpan>? provider) => provider is not null;
Prevention
- Always pass a non-null backoff provider; use a named helper for common strategies.
- Enable nullable reference types so null providers are flagged at compile time.
- Default provider fields to a sensible exponential backoff.
When it happens
Trigger: Calling Policy.Handle<...>().WaitAndRetry(retryCount, null, onRetry) with null for the Func<int, TimeSpan> sleepDurationProvider at RetrySyntax.cs:270.
Common situations: Passing a backoff factory variable that is null; conditional wiring where the provider is only set in one branch; refactor that replaced the lambda with a null placeholder.
Related errors
- onRetry
- Value must be greater than or equal to zero.
- Value cannot be null.
- Value cannot be null. (Parameter 'cacheProvider')
- Value cannot be null. (Parameter 'cacheKeyStrategy')
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/2b3a8e7df1aaf5c1.
Report an issue: GitHub.