{"record":{"id":"77f4014c0db52ecb","repo":"App-vNext/Polly","slug":"onretry-77f401","errorCode":null,"errorMessage":"onRetry","messagePattern":"onRetry","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Retry/RetrySyntax.cs","lineNumber":138,"sourceCode":"            throw new ArgumentNullException(nameof(onRetry));\n        }\n\n        return policyBuilder.RetryForever((Exception outcome, Context _) => onRetry(outcome));\n    }\n\n    /// <summary>\n    /// Builds a <see cref=\"Policy\"/> that will retry indefinitely\n    /// calling <paramref name=\"onRetry\"/> on each retry with the raised exception and retry count.\n    /// </summary>\n    /// <param name=\"policyBuilder\">The policy builder.</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=\"onRetry\"/> is <see langword=\"null\"/>.</exception>\n    public static RetryPolicy RetryForever(this PolicyBuilder policyBuilder, Action<Exception, int> onRetry)\n    {\n        if (onRetry == null)\n        {\n            throw new ArgumentNullException(nameof(onRetry));\n        }\n\n        return policyBuilder.RetryForever((outcome, i, _) => onRetry(outcome, i));\n    }\n\n    /// <summary>\n    /// Builds a <see cref=\"Policy\"/> that will retry indefinitely\n    /// calling <paramref name=\"onRetry\"/> on each retry with the raised exception and context data.\n    /// </summary>\n    /// <param name=\"policyBuilder\">The policy builder.</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=\"onRetry\"/> is <see langword=\"null\"/>.</exception>\n    public static RetryPolicy RetryForever(this PolicyBuilder policyBuilder, Action<Exception, Context> onRetry)\n    {\n        if (onRetry == null)\n        {\n            throw new ArgumentNullException(nameof(onRetry));","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Retry/RetrySyntax.cs#L120-L156","documentation":"Thrown by the legacy Polly v7 synchronous RetryForever API when the onRetry callback (Action<Exception, int>) is null. RetryForever wires the callback into the policy so it fires on every retry indefinitely; a null callback would NRE on the first retry, so Polly validates it at construction.","triggerScenarios":"Calling Policy.Handle<...>().RetryForever(null) with null for the Action<Exception, int> parameter at RetrySyntax.cs:138.","commonSituations":"Forgetting to pass the callback; passing a handler variable that is null; refactoring that removed the logging body; intending the parameterless RetryForever overload.","solutions":["Provide a non-null Action<Exception, int>, e.g. (ex, retryCount) => _logger.Error(ex, \"Retry {RetryCount}\", retryCount).","Use the parameterless RetryForever overload if you do not need a per-retry callback.","Initialize handler fields to a no-op action instead of null."],"exampleFix":"// before\nvar policy = Policy.Handle<SocketException>().RetryForever(null);\n// after\nvar policy = Policy.Handle<SocketException>().RetryForever((ex, retryCount) => _logger.Warning(ex, \"Retry {Count}\", retryCount));","handlingStrategy":"validation","validationCode":"if (onRetry is null)\n    throw new InvalidOperationException(\"onRetry callback is required.\");\nvar policy = Policy.Handle<TException>(pred).RetryForever(onRetry);","typeGuard":"static bool IsValid(Action<Exception, int>? cb) => cb is not null;","tryCatchPattern":null,"preventionTips":["Always pass a non-null callback; use the parameterless RetryForever overload otherwise.","Default handler fields to a no-op action.","Enable nullable reference types."],"tags":["argumentnullexception","polly","retry","sync","validation","csharp","legacy-api"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}