App-vNext/Polly · error · ArgumentNullException
sleepDurations
Error message
sleepDurations
What it means
ArgumentNullException is thrown when sleepDurations is null in the terminal WaitAndRetryAsync(IEnumerable<TimeSpan> sleepDurations, Func<Exception,TimeSpan,int,Context,Task> onRetryAsync) overload. All convenience overloads (errors 203-207) delegate here, so a null sleepDurations passed to any of them surfaces at this guard. The enumerable defines both the number of retries and the wait duration for each.
Source
Thrown at src/Polly/Retry/AsyncRetrySyntax.cs:832
#pragma warning restore 1998
}
/// <summary>
/// Builds an <see cref="AsyncRetryPolicy" /> that will wait and retry as many times as there are provided
/// <paramref name="sleepDurations" />
/// calling <paramref name="onRetryAsync" /> on each retry with the raised exception, the current sleep duration, retry count, and context data.
/// On each retry, the duration to wait is the current <paramref name="sleepDurations" /> item.
/// </summary>
/// <param name="policyBuilder">The policy builder.</param>
/// <param name="sleepDurations">The sleep durations to wait for on each retry.</param>
/// <param name="onRetryAsync">The action to call asynchronously on each retry.</param>
/// <returns>The policy instance.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="sleepDurations"/> or <paramref name="onRetryAsync"/> is <see langword="null"/>.</exception>
public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilder, IEnumerable<TimeSpan> sleepDurations, Func<Exception, TimeSpan, int, Context, Task> onRetryAsync)
{
if (sleepDurations == null)
{
throw new ArgumentNullException(nameof(sleepDurations));
}
if (onRetryAsync == null)
{
throw new ArgumentNullException(nameof(onRetryAsync));
}
return new AsyncRetryPolicy(
policyBuilder,
onRetryAsync,
sleepDurationsEnumerable: sleepDurations);
}
/// <summary>
/// Builds an <see cref="AsyncRetryPolicy"/> that will wait and retry indefinitely until the action succeeds.
/// On each retry, the duration to wait is calculated by calling <paramref name="sleepDurationProvider" /> with
/// the current retry number (1 for first retry, 2 for second etc).
/// </summary>View on GitHub (pinned to d0e46bdb1e)
Solutions
- Supply an explicit list: new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(4) }.
- If building from config, ensure the binding target is initialized and verify with a null check before calling the policy.
- Return Enumerable.Empty<TimeSpan>() instead of null from helper methods.
Example fix
// before
var durations = config.GetSection("Backoff").Get<IEnumerable<TimeSpan>>();
Policy.Handle<HttpRequestException>().WaitAndRetryAsync(durations, onRetry);
// after
var durations = config.GetSection("Backoff").Get<List<TimeSpan>>() ?? new List<TimeSpan> { TimeSpan.FromSeconds(1) };
Policy.Handle<HttpRequestException>().WaitAndRetryAsync(durations, onRetry); Defensive patterns
Strategy: validation
Validate before calling
sleepDurations ??= new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(4) };
if (!sleepDurations.Any())
throw new InvalidOperationException("At least one sleep duration is required."); Type guard
static bool IsValidDurations(IEnumerable<TimeSpan> durations)
=> durations is not null && durations.Any(); Prevention
- Never return null from helper methods that build backoff schedules — use Enumerable.Empty<TimeSpan>() or a default list.
- Validate config-bound durations at startup with a null check and fallback.
- Inline the durations array when the schedule is static.
When it happens
Trigger: Passing null where an IEnumerable<TimeSpan> is expected — typically from a configuration method that returned null, a LINQ query that produced no results and was then overwritten, or a factory that failed silently.
Common situations: A backoff schedule read from JSON config that deserialized to null because the section name was mistyped, or a helper method returning null instead of an empty enumerable.
Related errors
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/7a2a5a276d6fcc60.
Report an issue: GitHub.