apache/dubbo · error · IllegalArgumentException

ticksPerWheel may not be greater than 2^30: {}

Error message

ticksPerWheel may not be greater than 2^30: {}

What it means

IllegalArgumentException thrown by createWheel() when ticksPerWheel exceeds 1073741824 (2^30). The wheel size is normalized to the next power of two, so values above 2^30 would normalize to 2^31, which overflows int range for array allocation (Integer.MAX_VALUE = 2^31 - 1). The cap at 2^30 ensures the normalized power-of-two fits in a Java int array. Allocating such a massive wheel is also impractical in terms of memory.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java:286

    protected void finalize() throws Throwable {
        try {
            super.finalize();
        } finally {
            // This object is going to be GCed and it is assumed the ship has sailed to do a proper shutdown. If
            // we have not yet shutdown then we want to make sure we decrement the active instance count.
            if (WORKER_STATE_UPDATER.getAndSet(this, WORKER_STATE_SHUTDOWN) != WORKER_STATE_SHUTDOWN) {
                INSTANCE_COUNTER.decrementAndGet();
            }
        }
    }

    private static HashedWheelBucket[] createWheel(int ticksPerWheel) {
        if (ticksPerWheel <= 0) {
            throw new IllegalArgumentException(
                "ticksPerWheel must be greater than 0: " + ticksPerWheel);
        }
        if (ticksPerWheel > 1073741824) {
            throw new IllegalArgumentException(
                "ticksPerWheel may not be greater than 2^30: " + ticksPerWheel);
        }

        ticksPerWheel = normalizeTicksPerWheel(ticksPerWheel);
        HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel];
        for (int i = 0; i < wheel.length; i++) {
            wheel[i] = new HashedWheelBucket();
        }
        return wheel;
    }

    private static int normalizeTicksPerWheel(int ticksPerWheel) {
        int normalizedTicksPerWheel = ticksPerWheel - 1;
        normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 1;
        normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 2;
        normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 4;
        normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 8;
        normalizedTicksPerWheel |= normalizedTicksPerWheel >>> 16;

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Use a reasonable wheel size — 512 is the default and sufficient for most workloads. Larger wheels (e.g., 2048, 4096) only help with very high timeout throughput.
  2. Validate the wheel size before construction and cap it to a sane maximum.
  3. Review how the wheel size value is computed or configured to find the source of the inflated number.

Example fix

// before
int size = computeWheelSize(); // accidentally returns Integer.MAX_VALUE
new HashedWheelTimer(factory, 100, TimeUnit.MILLISECONDS, size);

// after
int size = computeWheelSize();
if (size <= 0) size = 512;
if (size > 4096) size = 4096; // cap to reasonable max
new HashedWheelTimer(factory, 100, TimeUnit.MILLISECONDS, size);
Defensive patterns

Strategy: validation

Validate before calling

if (ticksPerWheel > 1073741824) {
    throw new IllegalArgumentException("ticksPerWheel too large: " + ticksPerWheel);
}
int safeWheel = ticksPerWheel;
if (safeWheel > 4096) safeWheel = 4096; // cap to practical maximum
new HashedWheelTimer(factory, tickDuration, unit, safeWheel);

Prevention

When it happens

Trigger: Passing a ticksPerWheel value greater than 1,073,741,824 (2^30) to the HashedWheelTimer constructor. The constructor's check (line 241) only rejects <= 0, so values up to 2^30 reach createWheel() which enforces the upper bound.

Common situations: Configuration or computed value that produces an extremely large wheel size; misunderstanding of the parameter leading to an unreasonably large value; arithmetic overflow in the caller's computation that yields a huge positive number.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/e0ed670d361d8992. Report an issue: GitHub.