{"record":{"id":"43136196125b23df","repo":"App-vNext/Polly","slug":"the-number-of-executions-per-timespan-must-be-posi","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/AsyncRateLimitSyntax.cs","lineNumber":49,"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(rateLimiter);\n    }\n}\n","sourceCodeStart":31,"sourceCodeEnd":57,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/RateLimit/AsyncRateLimitSyntax.cs#L31-L57","documentation":"Thrown by RateLimitAsync when the computed per-execution interval (perTimeSpan.Ticks / numberOfExecutions) is less than or equal to TimeSpan.Zero. Because both numberOfExecutions and perTimeSpan are already validated positive, this guard catches integer-division edge cases where perTimeSpan.Ticks is smaller than numberOfExecutions, yielding zero ticks (sub-tick intervals cannot be represented).","triggerScenarios":"Configuring a high numberOfExecutions against a tiny perTimeSpan such that perTimeSpan.Ticks / numberOfExecutions rounds down to zero. Example: RateLimitAsync(1000, TimeSpan.FromMilliseconds(1), burst) - 1ms is 10000 ticks, divided by 1000 = 10 ticks (ok), but TimeSpan.FromTicks(1) / 1000 = 0 ticks triggers it.","commonSituations":"Aggressive high-rate configs where the desired per-execution cadence is below one tick (~100ns); mis-scaled units (per-second count applied to a per-millisecond window); dynamic config that scales executions up without scaling the window.","solutions":["Ensure perTimeSpan.Ticks >= numberOfExecutions so the per-execution interval is at least one tick; widen perTimeSpan or reduce numberOfExecutions.","Reconsider the units: express the rate as executions-per-second with a one-second window.","Validate the derived onePer interval before constructing the policy.","If you need sub-tick granularity, the legacy LockFreeTokenBucketRateLimiter cannot represent it - use the v8 Polly.RateLimiting (System.Threading.RateLimiting) package instead."],"exampleFix":"// before\n// 1 tick / 10 executions = 0 ticks -> throws\nvar p = Policy.RateLimitAsync(10, TimeSpan.FromTicks(1), 10);\n\n// after\nvar p = Policy.RateLimitAsync(10, TimeSpan.FromSeconds(1), 10);","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(numberOfExecutions, perTimeSpan, maxBurst);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Express rates as executions-per-second with a one-second window to avoid sub-tick math.","Ensure perTimeSpan.Ticks >= numberOfExecutions before constructing the policy.","For sub-tick rates, migrate to Polly v8 RateLimiting (System.Threading.RateLimiting)."],"tags":["argumentoutofrange","ratelimit","config","validation","timespan","legacy-api"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}