{"record":{"id":"838abf9b052b3297","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-action-838abf","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'action')","messagePattern":"Value cannot be null\\. \\(Parameter 'action'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/RateLimit/RateLimitPolicy.cs","lineNumber":20,"sourceCode":"namespace Polly.RateLimit;\n\n/// <summary>\n/// A rate-limit policy that can be applied to synchronous delegates.\n/// </summary>\npublic class RateLimitPolicy : Policy, IRateLimitPolicy\n{\n    private readonly IRateLimiter _rateLimiter;\n\n    internal RateLimitPolicy(IRateLimiter rateLimiter) =>\n        _rateLimiter = rateLimiter;\n\n    /// <inheritdoc/>\n    [DebuggerStepThrough]\n    protected override TResult Implementation<TResult>(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken)\n    {\n        if (action is null)\n        {\n            throw new ArgumentNullException(nameof(action));\n        }\n\n        return RateLimitEngine.Implementation(_rateLimiter, null, action, context, cancellationToken);\n    }\n}\n\n/// <summary>\n/// A rate-limit policy that can be applied to synchronous delegates returning a value of type <typeparamref name=\"TResult\"/>.\n/// </summary>\n/// <typeparam name=\"TResult\">The type of the result.</typeparam>\npublic class RateLimitPolicy<TResult> : Policy<TResult>, IRateLimitPolicy<TResult>\n{\n    private readonly IRateLimiter _rateLimiter;\n    private readonly Func<TimeSpan, Context, TResult>? _retryAfterFactory;\n\n    internal RateLimitPolicy(\n        IRateLimiter rateLimiter,\n        Func<TimeSpan, Context, TResult>? retryAfterFactory)","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/RateLimit/RateLimitPolicy.cs#L2-L38","documentation":"Thrown by RateLimitPolicy.Implementation<TResult> (synchronous) when the action delegate is null. This is the factory-less sync rate limit policy; the guard mirrors every other Polly strategy: validate the delegate before invoking RateLimitEngine.","triggerScenarios":"Calling Implementation with a null action on a RateLimitPolicy instance. Normally reached through internal Policy.Execute plumbing when a null delegate reaches the strategy, or via direct subclass/reflection.","commonSituations":"A wrapper that conditionally forwards a delegate and passes null; default(Func<...>) assigned and forwarded; reflection-driven test invocation of the protected member.","solutions":["Pass a non-null Func<Context, CancellationToken, TResult> to Execute.","Branch around the call when the delegate is optional rather than passing null.","Add a precondition null check in your caller.","Enable nullable reference types to surface nullable delegates at compile time."],"exampleFix":"// before\nrlPolicy.Execute<int>(null, context, ct);\n\n// after\nrlPolicy.Execute<int>((ctx, ct) => 42, context, ct);","handlingStrategy":"validation","validationCode":"if (action is null) throw new ArgumentNullException(nameof(action));\nrlPolicy.Execute(action ?? throw new ArgumentNullException(nameof(action)), context, ct);","typeGuard":"static bool IsFunc<T>(Delegate d) => d is Func<Context, CancellationToken, T>;","tryCatchPattern":null,"preventionTips":["Never pass default(Func<...>) to a sync Execute.","Validate delegates at your wrapper boundary.","Enable NRTs so nullable delegates surface at compile time."],"tags":["argumentnullexception","action","validation","ratelimit","legacy-api"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}