{"record":{"id":"9e7c1bdb40256c8f","repo":"App-vNext/Polly","slug":"the-number-of-executions-per-timespan-must-be-posi-9e7c1b","errorCode":null,"errorMessage":"The number of executions per timespan must be positive.","messagePattern":"The number of executions per timespan must be positive\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Polly/RateLimit/AsyncRateLimitTResultSyntax.cs","lineNumber":85,"sourceCode":"        {\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        }\n\n        IRateLimiter rateLimiter = new LockFreeTokenBucketRateLimiter(onePer, maxBurst);\n\n        return new AsyncRateLimitPolicy<TResult>(rateLimiter, retryAfterFactory);\n    }\n}\n","sourceCodeStart":67,"sourceCodeEnd":93,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/RateLimit/AsyncRateLimitTResultSyntax.cs#L67-L93","documentation":"Thrown by the typed RateLimitAsync<TResult> overload when the derived per-execution interval (perTimeSpan.Ticks / numberOfExecutions) rounds down to zero ticks. Same edge case as the factory-less variant: a high execution count against a window with fewer ticks than executions produces a sub-tick interval that cannot be represented.","triggerScenarios":"Configuring RateLimitAsync<TResult>(n, perTimeSpan, burst, factory) where perTimeSpan.Ticks < numberOfExecutions. The retryAfterFactory does not affect this arithmetic guard.","commonSituations":"Very high rates against tiny windows; mis-scaled units (per-second counts on per-millisecond windows); dynamically-scaled execution counts that outgrow the window's tick resolution.","solutions":["Widen perTimeSpan or reduce numberOfExecutions so perTimeSpan.Ticks >= numberOfExecutions.","Express the rate in executions-per-second with a one-second window.","Validate the derived interval before constructing the policy.","For sub-tick rates, migrate to Polly v8 (Polly.RateLimiting backed by System.Threading.RateLimiting)."],"exampleFix":"// before\n// 1 tick / 5 executions = 0 -> throws\nvar p = Policy.RateLimitAsync<int>(5, TimeSpan.FromTicks(1), 5, null);\n\n// after\nvar p = Policy.RateLimitAsync<int>(5, TimeSpan.FromSeconds(1), 5, null);","handlingStrategy":"validation","validationCode":"if (perTimeSpan.Ticks < numberOfExecutions)\n    throw new ArgumentOutOfRangeException(nameof(perTimeSpan), \"perTimeSpan must have at least one tick per execution\");\nvar p = Policy.RateLimitAsync<TResult>(numberOfExecutions, perTimeSpan, maxBurst, retryAfterFactory);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Express the rate in executions-per-second with a one-second window.","Guarantee perTimeSpan.Ticks >= numberOfExecutions before constructing the policy.","For rates faster than one tick per execution, use Polly v8 RateLimiting."],"tags":["argumentoutofrange","ratelimit","config","validation","timespan","tresult","legacy-api"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}