{"record":{"id":"7f8d2e164d92b6a4","repo":"App-vNext/Polly","slug":"onretryasync","errorCode":null,"errorMessage":"onRetryAsync","messagePattern":"onRetryAsync","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Retry/AsyncRetrySyntax.cs","lineNumber":784,"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 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, Context, Task> onRetryAsync)\n    {\n        if (onRetryAsync == null)\n        {\n            throw new ArgumentNullException(nameof(onRetryAsync));\n        }\n\n        return policyBuilder.WaitAndRetryAsync(\n            sleepDurations,\n            onRetryAsync: (outcome, timespan, _, ctx) => onRetryAsync(outcome, timespan, ctx));\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=\"onRetry\" /> 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=\"onRetry\">The action to call on each retry.</param>\n    /// <returns>The policy instance.</returns>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"sleepDurations\"/> or <paramref name=\"onRetry\"/> is <see langword=\"null\"/>.</exception>","sourceCodeStart":766,"sourceCodeEnd":802,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Retry/AsyncRetrySyntax.cs#L766-L802","documentation":"ArgumentNullException is thrown when onRetryAsync is null in WaitAndRetryAsync(IEnumerable<TimeSpan> sleepDurations, Func<Exception,TimeSpan,Context,Task> onRetryAsync). This is the async counterpart of error 205 and wraps into the full 4-parameter delegate.","triggerScenarios":"Calling this overload with a null async callback delegate that includes Context.","commonSituations":"DI registration that did not bind the callback, or a refactor that removed the callback while keeping the overload choice.","solutions":["Provide a Task-returning lambda accepting Context.","Use the overload without callback if none is needed.","Use a no-op default: (ex, delay, ctx) => Task.CompletedTask."],"exampleFix":"// before\n.WaitAndRetryAsync(durations, null)\n\n// after\n.WaitAndRetryAsync(durations, (ex, delay, ctx) =>\n{\n    logger.LogWarning(\"Retry {Id} after {Delay}\", ctx.OperationKey, delay);\n    return Task.CompletedTask;\n})","handlingStrategy":"validation","validationCode":"if (onRetryAsync is null)\n    onRetryAsync = (_, _, _) => Task.CompletedTask;","typeGuard":"static bool IsValidCallback(Func<Exception, TimeSpan, Context, Task> cb) => cb is not null;","tryCatchPattern":null,"preventionTips":["Default async context-aware callbacks to Task.CompletedTask.","Confirm DI registration before policy construction."],"tags":["retry","argument-validation","null-reference","polly-v7"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}