{"record":{"id":"373e072803941eda","repo":"App-vNext/Polly","slug":"numberofexecutions-per-timespan-must-be-an-integer","errorCode":null,"errorMessage":"numberOfExecutions per timespan must be an integer greater than or equal to 1.","messagePattern":"numberOfExecutions per timespan must be an integer greater than or equal to 1\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Polly/RateLimit/AsyncRateLimitSyntax.cs","lineNumber":32,"sourceCode":"        TimeSpan perTimeSpan) =>\n        RateLimitAsync(numberOfExecutions, perTimeSpan, 1);\n\n    /// <summary>\n    /// Builds a RateLimit <see cref=\"AsyncPolicy\"/> that will rate-limit executions to <paramref name=\"numberOfExecutions\"/> per the timespan given.\n    /// </summary>\n    /// <param name=\"numberOfExecutions\">The number of executions (call it N) permitted per timespan.</param>\n    /// <param name=\"perTimeSpan\">How often N executions are permitted.</param>\n    /// <param name=\"maxBurst\">The maximum number of executions that will be permitted in a single burst (for example if none have been executed for a while).\n    /// This equates to the bucket-capacity of a token-bucket implementation.</param>\n    /// <returns>The policy instance.</returns>\n    public static AsyncRateLimitPolicy RateLimitAsync(\n        int numberOfExecutions,\n        TimeSpan perTimeSpan,\n        int maxBurst)\n    {\n        if (numberOfExecutions < 1)\n        {\n            throw new ArgumentOutOfRangeException(nameof(numberOfExecutions), numberOfExecutions, $\"{nameof(numberOfExecutions)} per timespan must be an integer greater than or equal to 1.\");\n        }\n\n        if (perTimeSpan <= TimeSpan.Zero)\n        {\n            throw new ArgumentOutOfRangeException(nameof(perTimeSpan), perTimeSpan, $\"{nameof(perTimeSpan)} must be a positive timespan.\");\n        }\n\n        if (maxBurst < 1)\n        {\n            throw new ArgumentOutOfRangeException(nameof(maxBurst), maxBurst, $\"{nameof(maxBurst)} must be an integer greater than or equal to 1.\");\n        }\n\n        var onePer = TimeSpan.FromTicks(perTimeSpan.Ticks / numberOfExecutions);\n\n        if (onePer <= TimeSpan.Zero)\n        {\n            throw new ArgumentOutOfRangeException(nameof(perTimeSpan), perTimeSpan, \"The number of executions per timespan must be positive.\");\n        }","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/RateLimit/AsyncRateLimitSyntax.cs#L14-L50","documentation":"Thrown by RateLimitAsync(int, TimeSpan, int) (the factory-less overload) when numberOfExecutions is less than 1. numberOfExecutions defines how many executions are permitted per perTimeSpan window, so zero or negative values are meaningless. The guard is the first of three sequential config validations.","triggerScenarios":"Calling Policy.RateLimitAsync(0, ts, burst) or with a negative numberOfExecutions. Common when the value is derived from configuration without clamping.","commonSituations":"Reading numberOfExecutions from appsettings/environment where it is missing (parses to 0), mis-scaled units (per-second value used as per-minute), or a feature flag disabling a limit by setting it to 0.","solutions":["Set numberOfExecutions to a positive integer that reflects measured throughput, e.g. 100.","Validate/clamp the config value before passing it: Math.Max(1, parsedValue).","Distinguish 'disable rate limiting' (do not create the policy at all) from 'zero executions'.","Add an integration test that constructs the policy with realistic config to catch bad values early."],"exampleFix":"// before\nvar p = Policy.RateLimitAsync(0, TimeSpan.FromSeconds(1), 10);\n\n// after\nvar p = Policy.RateLimitAsync(10, TimeSpan.FromSeconds(1), 10);","handlingStrategy":"validation","validationCode":"int n = Math.Max(1, parsedNumberOfExecutions);\nif (n < 1) throw new ArgumentOutOfRangeException(nameof(n));\nvar p = Policy.RateLimitAsync(n, perTimeSpan, maxBurst);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate rate-limit config at startup with an assertion on all three bounds.","Clamp config-derived values with Math.Max(1, value).","Treat 'disable rate limiting' as 'skip policy construction', not 'set to 0'.","Unit-test policy construction with realistic config values."],"tags":["argumentoutofrange","ratelimit","config","validation","legacy-api"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}