{"record":{"id":"7a2a5a276d6fcc60","repo":"App-vNext/Polly","slug":"sleepdurations","errorCode":null,"errorMessage":"sleepDurations","messagePattern":"sleepDurations","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Retry/AsyncRetrySyntax.cs","lineNumber":832,"sourceCode":"#pragma warning restore 1998\n    }\n\n    /// <summary>\n    ///     Builds an <see cref=\"AsyncRetryPolicy\" /> that will wait and retry as many times as there are provided\n    ///     <paramref name=\"sleepDurations\" />\n    ///     calling <paramref name=\"onRetryAsync\" /> on each retry with the raised exception, the current sleep duration, retry count, and context data.\n    ///     On each retry, the duration to wait is the current <paramref name=\"sleepDurations\" /> item.\n    /// </summary>\n    /// <param name=\"policyBuilder\">The policy builder.</param>\n    /// <param name=\"sleepDurations\">The sleep durations to wait for on each retry.</param>\n    /// <param name=\"onRetryAsync\">The action to call asynchronously on each retry.</param>\n    /// <returns>The policy instance.</returns>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"sleepDurations\"/> or <paramref name=\"onRetryAsync\"/> is <see langword=\"null\"/>.</exception>\n    public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilder, IEnumerable<TimeSpan> sleepDurations, Func<Exception, TimeSpan, int, Context, Task> onRetryAsync)\n    {\n        if (sleepDurations == null)\n        {\n            throw new ArgumentNullException(nameof(sleepDurations));\n        }\n\n        if (onRetryAsync == null)\n        {\n            throw new ArgumentNullException(nameof(onRetryAsync));\n        }\n\n        return new AsyncRetryPolicy(\n            policyBuilder,\n            onRetryAsync,\n            sleepDurationsEnumerable: sleepDurations);\n    }\n\n    /// <summary>\n    /// Builds an <see cref=\"AsyncRetryPolicy\"/> that will wait and retry indefinitely until the action succeeds.\n    ///     On each retry, the duration to wait is calculated by calling <paramref name=\"sleepDurationProvider\" /> with\n    ///     the current retry number (1 for first retry, 2 for second etc).\n    /// </summary>","sourceCodeStart":814,"sourceCodeEnd":850,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Retry/AsyncRetrySyntax.cs#L814-L850","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar durations = config.GetSection(\"Backoff\").Get<IEnumerable<TimeSpan>>();\nPolicy.Handle<HttpRequestException>().WaitAndRetryAsync(durations, onRetry);\n\n// after\nvar durations = config.GetSection(\"Backoff\").Get<List<TimeSpan>>() ?? new List<TimeSpan> { TimeSpan.FromSeconds(1) };\nPolicy.Handle<HttpRequestException>().WaitAndRetryAsync(durations, onRetry);","handlingStrategy":"validation","validationCode":"sleepDurations ??= new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(4) };\nif (!sleepDurations.Any())\n    throw new InvalidOperationException(\"At least one sleep duration is required.\");","typeGuard":"static bool IsValidDurations(IEnumerable<TimeSpan> durations)\n    => durations is not null && durations.Any();","tryCatchPattern":null,"preventionTips":["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."],"tags":["retry","argument-validation","null-reference","configuration","polly-v7"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}