{"record":{"id":"9051e28ba8fc08eb","repo":"alibaba/Sentinel","slug":"maxtokens-should-0-but-given","errorCode":null,"errorMessage":"maxTokens should > 0, but given: ","messagePattern":"maxTokens should > 0, but given: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/TokenBucket.java","lineNumber":32,"sourceCode":" * limitations under the License.\n */\npackage com.alibaba.csp.sentinel.eagleeye;\n\nimport java.util.concurrent.atomic.AtomicLong;\n\nclass TokenBucket {\n\n    private final long maxTokens;\n\n    private final long intervalMillis;\n\n    private volatile long nextUpdate;\n\n    private AtomicLong tokens;\n\n    public TokenBucket(long maxTokens, long intervalMillis) {\n        if (maxTokens <= 0) {\n            throw new IllegalArgumentException(\"maxTokens should > 0, but given: \" + maxTokens);\n        }\n        if (intervalMillis < 1000) {\n            throw new IllegalArgumentException(\"intervalMillis should be at least 1000, but given: \" + intervalMillis);\n        }\n        this.maxTokens = maxTokens;\n        this.intervalMillis = intervalMillis;\n        this.nextUpdate = System.currentTimeMillis() / 1000 * 1000 + intervalMillis;\n        this.tokens = new AtomicLong(maxTokens);\n    }\n\n    public boolean accept(long now) {\n        long currTokens;\n        if (now > nextUpdate) {\n            currTokens = tokens.get();\n            if (tokens.compareAndSet(currTokens, maxTokens)) {\n                nextUpdate = System.currentTimeMillis() / 1000 * 1000 + intervalMillis;\n            }\n        }","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/TokenBucket.java#L14-L50","documentation":"TokenBucket (EagleEye core, used for fast-scrolling log tracing rate control) requires maxTokens > 0. The constructor validates the bucket capacity because a zero or negative capacity would make the token bucket unable to accept or refill any request. It throws IllegalArgumentException immediately at construction time.","triggerScenarios":"new TokenBucket(maxTokens, intervalMillis) with maxTokens <= 0, e.g. new TokenBucket(0, 1000) or a negative capacity computed from a config value.","commonSituations":"Passing a rate limit or a computed tokens-per-interval value that underflows to 0 (e.g. 'events per second * interval' where one factor is 0), or loading a missing/typoed property that defaults to 0.","solutions":["Check the value passed as maxTokens and ensure it is at least 1 before constructing TokenBucket.","Trace where the maxTokens argument comes from (config/property) and fix the source producing 0 or a negative number.","Add a unit assertion/ precondition in your config loader so invalid capacities fail fast with a clearer message."],"exampleFix":"// before\nnew TokenBucket(ratePerSec * 0, 1000);\n\n// after\nlong maxTokens = Math.max(1, ratePerSec);\nnew TokenBucket(maxTokens, 1000);","handlingStrategy":"validation","validationCode":"long maxTokens = computeCapacity();\nif (maxTokens <= 0) {\n    throw new ConfigurationException(\"token bucket capacity must be > 0, got \" + maxTokens);\n}\nTokenBucket bucket = new TokenBucket(maxTokens, 1000);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive maxTokens from validated config values, never from unchecked arithmetic that can yield 0.","Wrap construction in a factory method that enforces capacity > 0 for all buckets."],"tags":["sentinel","eagleeye","rate-limit","constructor-validation"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}