apache/dubbo · error · IllegalArgumentException
tickDuration must be greater than 0: {}
Error message
tickDuration must be greater than 0: {} What it means
IllegalArgumentException thrown by the HashedWheelTimer constructor when tickDuration is <= 0. The tick duration defines the interval between wheel ticks (the timer's resolution). A non-positive tick duration is nonsensical — the timer could never advance. The constructor validates this before allocating the wheel structure. Note this checks the raw input value before unit conversion to nanos.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java:238
* {@link java.util.concurrent.RejectedExecutionException}
* being thrown. No maximum pending timeouts limit is assumed if
* this value is 0 or negative.
* @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null}
* @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0
*/
public HashedWheelTimer(
ThreadFactory threadFactory,
long tickDuration, TimeUnit unit, int ticksPerWheel,
long maxPendingTimeouts) {
if (threadFactory == null) {
throw new NullPointerException("threadFactory");
}
if (unit == null) {
throw new NullPointerException("unit");
}
if (tickDuration <= 0) {
throw new IllegalArgumentException("tickDuration must be greater than 0: " + tickDuration);
}
if (ticksPerWheel <= 0) {
throw new IllegalArgumentException("ticksPerWheel must be greater than 0: " + ticksPerWheel);
}
// Normalize ticksPerWheel to power of two and initialize the wheel.
wheel = createWheel(ticksPerWheel);
mask = wheel.length - 1;
// Convert tickDuration to nanos.
this.tickDuration = unit.toNanos(tickDuration);
// Prevent overflow.
if (this.tickDuration >= Long.MAX_VALUE / wheel.length) {
throw new IllegalArgumentException(String.format(
"tickDuration: %d (expected: 0 < tickDuration in nanos < %d",
tickDuration, Long.MAX_VALUE / wheel.length));
}View on GitHub (pinned to 3a3043227f)
Solutions
- Set tickDuration to a positive value — 100 (milliseconds) is the Dubbo/Netty default and is appropriate for most I/O timeout use cases.
- Validate the configured/computed tickDuration before construction and fall back to a sensible default.
- Check for unit mismatches that cause the value to collapse to 0 (e.g., passing nanoseconds where milliseconds are expected).
Example fix
// before long tick = config.getTickDuration(); // 0 if unset new HashedWheelTimer(factory, tick, TimeUnit.MILLISECONDS, 512); // after long tick = config.getTickDuration(); if (tick <= 0) tick = 100; // default to 100ms new HashedWheelTimer(factory, tick, TimeUnit.MILLISECONDS, 512);
Defensive patterns
Strategy: validation
Validate before calling
if (tickDuration <= 0) {
throw new IllegalArgumentException("tickDuration must be positive, got: " + tickDuration);
}
// or default:
long safeTick = tickDuration > 0 ? tickDuration : 100L; // 100ms default
new HashedWheelTimer(factory, safeTick, unit, ticksPerWheel); Prevention
- Validate tickDuration is positive before constructing the timer.
- Default to 100 (milliseconds) — the standard resolution for I/O timeouts.
- Check configuration parsing to ensure the value isn't accidentally 0.
When it happens
Trigger: Passing a tickDuration of 0 or a negative number to the HashedWheelTimer constructor. This can happen when the value is read from configuration that defaulted to 0, or computed from a formula that yields zero/negative.
Common situations: Configuration property (e.g., a timeout or tick interval) set to 0 or left unset defaulting to 0; computed duration that evaluates to zero due to integer division or unit mismatch; test code passing 0 as a placeholder.
Related errors
- ticksPerWheel must be greater than 0: {}
- threadFactory
- unit
- tickDuration: %d (expected: 0 < tickDuration in nanos < %d
- ticksPerWheel may not be greater than 2^30: {}
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/3190563e2de222dc.
Report an issue: GitHub.