{"record":{"id":"85dc5a6d10573080","repo":"App-vNext/Polly","slug":"onretry","errorCode":null,"errorMessage":"onRetry","messagePattern":"onRetry","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Retry/AsyncRetrySyntax.cs","lineNumber":807,"sourceCode":"            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>\n    public static AsyncRetryPolicy WaitAndRetryAsync(this PolicyBuilder policyBuilder, IEnumerable<TimeSpan> sleepDurations, Action<Exception, TimeSpan, int, Context> onRetry)\n    {\n        if (onRetry == null)\n        {\n            throw new ArgumentNullException(nameof(onRetry));\n        }\n\n#pragma warning disable 1998 // async method has no awaits, will run synchronously\n        return policyBuilder.WaitAndRetryAsync(\n            sleepDurations,\n            onRetryAsync: async (outcome, timespan, i, ctx) => onRetry(outcome, timespan, i, ctx));\n#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>","sourceCodeStart":789,"sourceCodeEnd":825,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Retry/AsyncRetrySyntax.cs#L789-L825","documentation":"ArgumentNullException is thrown when onRetry is null in WaitAndRetryAsync(IEnumerable<TimeSpan> sleepDurations, Action<Exception,TimeSpan,int,Context> onRetry). This is the full-arity synchronous convenience overload that wraps into the terminal async overload.","triggerScenarios":"Calling this overload with a null onRetry action that receives exception, delay, retry count, and context.","commonSituations":"A full-arity callback left null because the developer copied the call from documentation but removed the callback body.","solutions":["Supply a non-null Action<Exception, TimeSpan, int, Context>.","Use the overload without callback: WaitAndRetryAsync(sleepDurations).","Default to a no-op: (ex, delay, retry, ctx) => { }."],"exampleFix":"// before\n.WaitAndRetryAsync(durations, null)\n\n// after\n.WaitAndRetryAsync(durations, (ex, delay, retry, ctx) =>\n    logger.LogWarning(\"Attempt {Retry} after {Delay}\", retry, delay))","handlingStrategy":"validation","validationCode":"if (onRetry is null)\n    onRetry = (_, _, _, _) => { };","typeGuard":"static bool IsValidCallback(Action<Exception, TimeSpan, int, Context> cb) => cb is not null;","tryCatchPattern":null,"preventionTips":["Default full-arity callbacks to a no-op.","Use the simpler overload without callback when telemetry is not required."],"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"}