alibaba/Sentinel · error · IllegalArgumentException

maxTokens should > 0, but given:

Error message

maxTokens should > 0, but given: 

What it means

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.

Solutions

  1. Check the value passed as maxTokens and ensure it is at least 1 before constructing TokenBucket.
  2. Trace where the maxTokens argument comes from (config/property) and fix the source producing 0 or a negative number.
  3. Add a unit assertion/ precondition in your config loader so invalid capacities fail fast with a clearer message.

Example fix

// before
new TokenBucket(ratePerSec * 0, 1000);

// after
long maxTokens = Math.max(1, ratePerSec);
new TokenBucket(maxTokens, 1000);
Defensive patterns

Strategy: validation

Validate before calling

long maxTokens = computeCapacity();
if (maxTokens <= 0) {
    throw new ConfigurationException("token bucket capacity must be > 0, got " + maxTokens);
}
TokenBucket bucket = new TokenBucket(maxTokens, 1000);

Prevention

When it happens

Trigger: new TokenBucket(maxTokens, intervalMillis) with maxTokens <= 0, e.g. new TokenBucket(0, 1000) or a negative capacity computed from a config value.

Common situations: 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.

Related errors


AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14). Data as JSON: /api/errors/9051e28ba8fc08eb. Report an issue: GitHub.

Appendix: source

Thrown at sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/TokenBucket.java:32

 * limitations under the License.
 */
package com.alibaba.csp.sentinel.eagleeye;

import java.util.concurrent.atomic.AtomicLong;

class TokenBucket {

    private final long maxTokens;

    private final long intervalMillis;

    private volatile long nextUpdate;

    private AtomicLong tokens;

    public TokenBucket(long maxTokens, long intervalMillis) {
        if (maxTokens <= 0) {
            throw new IllegalArgumentException("maxTokens should > 0, but given: " + maxTokens);
        }
        if (intervalMillis < 1000) {
            throw new IllegalArgumentException("intervalMillis should be at least 1000, but given: " + intervalMillis);
        }
        this.maxTokens = maxTokens;
        this.intervalMillis = intervalMillis;
        this.nextUpdate = System.currentTimeMillis() / 1000 * 1000 + intervalMillis;
        this.tokens = new AtomicLong(maxTokens);
    }

    public boolean accept(long now) {
        long currTokens;
        if (now > nextUpdate) {
            currTokens = tokens.get();
            if (tokens.compareAndSet(currTokens, maxTokens)) {
                nextUpdate = System.currentTimeMillis() / 1000 * 1000 + intervalMillis;
            }
        }

View on GitHub (pinned to a3f40ba8e9)