apache/dubbo · error · NullPointerException
unit
Error message
unit
What it means
NullPointerException thrown by the HashedWheelTimer constructor when the unit (TimeUnit) parameter is null. The tick duration is meaningless without a unit, and the constructor converts tickDuration to nanoseconds via unit.toNanos(), so a null unit would cause an NPE later anyway. The constructor fails fast with a clear message instead. TimeUnit is mandatory for any time-based configuration.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java:235
* @param ticksPerWheel the size of the wheel
* @param maxPendingTimeouts The maximum number of pending timeouts after which call to
* {@code newTimeout} will result in
* {@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(View on GitHub (pinned to 3a3043227f)
Solutions
- Always pass an explicit TimeUnit constant (e.g., TimeUnit.MILLISECONDS) — never a potentially-null variable.
- If deriving from configuration, validate and default the parsed TimeUnit before passing it to the constructor.
- Use the convenience constructors (e.g., HashedWheelTimer(tickDuration, unit)) that reduce the number of mandatory parameters.
Example fix
// before TimeUnit unit = parseUnit(config); // may return null new HashedWheelTimer(factory, 100, unit, 512); // after TimeUnit unit = parseUnit(config); if (unit == null) unit = TimeUnit.MILLISECONDS; new HashedWheelTimer(factory, 100, unit, 512);
Defensive patterns
Strategy: validation
Validate before calling
Objects.requireNonNull(unit, "unit must not be null"); TimeUnit safeUnit = unit != null ? unit : TimeUnit.MILLISECONDS; new HashedWheelTimer(threadFactory, tickDuration, safeUnit, ticksPerWheel);
Prevention
- Always pass an explicit TimeUnit constant (MILLISECONDS, SECONDS, etc.).
- Default to TimeUnit.MILLISECONDS when parsing configuration if the unit is missing.
- Use Objects.requireNonNull() to catch null early with a descriptive message.
When it happens
Trigger: Constructing a HashedWheelTimer with a null TimeUnit argument for the tickDuration parameter. A straightforward programming error of passing null where a TimeUnit enum value is required.
Common situations: Calling code that derives the TimeUnit from configuration or a variable that resolved to null; misconfigured properties mapping that fails to parse a time unit string into a TimeUnit enum.
Related errors
- threadFactory
- tickDuration must be greater than 0: {}
- ticksPerWheel must be greater than 0: {}
- Extension type == null
- Extension name == null
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/ec6ab9a83d142c85.
Report an issue: GitHub.