eclipse-vertx/vert.x · error · IllegalArgumentException
Invalid timer delay: ${delay}
Error message
Invalid timer delay: ${delay} What it means
Thrown by ContextInternal.timer(long, TimeUnit) when a non-positive delay is passed. Vert.x requires timer delays to be strictly greater than zero, so scheduling a timer, periodic timer, or delayed action with delay <= 0 fails fast before any Netty scheduling happens.
Source
Thrown at vertx-core/src/main/java/io/vertx/core/internal/ContextInternal.java:428
* Like {@link #timer(long, TimeUnit)} with a unit in millis.
*/
default Timer timer(long delay) {
return timer(delay, TimeUnit.MILLISECONDS);
}
/**
* Create a timer task configured with the specified {@code delay}, when the timeout fires the timer future
* is succeeded, when the timeout is cancelled the timer future is failed with a {@link java.util.concurrent.CancellationException}
* instance.
*
* @param delay the delay
* @param unit the delay unit
* @return the timer object
*/
default Timer timer(long delay, TimeUnit unit) {
Objects.requireNonNull(unit);
if (delay <= 0) {
throw new IllegalArgumentException("Invalid timer delay: " + delay);
}
io.netty.util.concurrent.ScheduledFuture<Void> fut = nettyEventLoop().schedule(() -> null, delay, unit);
TimerImpl timer = new TimerImpl(this, fut);
fut.addListener(timer);
return timer;
}
/**
* @return {@code true} when the context is associated with a deployment
*/
default boolean isDeployment() {
return deployment() != null;
}
default int getInstanceCount() {
DeploymentContext deployment = deployment();
if (deployment == null) {
return 0;View on GitHub (pinned to fb308bd8c3)
Solutions
- Ensure the delay is > 0 before calling timer(), e.g. Math.max(1, delayMs)
- If the deadline already passed (delay <= 0), execute the timeout action immediately instead of scheduling
- Fix the config/default so the timeout value is a positive number
Example fix
// before
ctx.timer(timeoutMs, TimeUnit.MILLISECONDS);
// after
if (timeoutMs <= 0) {
handleTimeoutNow();
} else {
ctx.timer(timeoutMs, TimeUnit.MILLISECONDS);
} Defensive patterns
Strategy: validation
Validate before calling
if (delay <= 0) throw new IllegalArgumentException("timer delay must be > 0, got " + delay); Try / catch
try { t = ctx.timer(delay, unit); } catch (IllegalArgumentException e) { handleImmediateTimeout(); } Prevention
- Treat 0/negative timeouts as 'immediate' and short-circuit before scheduling
- Validate config-sourced timeout values at startup
- Use Math.max(1, computedDelay) for remaining-deadline computations
When it happens
Trigger: Calling ctx.timer(0, TimeUnit.MILLISECONDS) or ctx.timer(-5, TimeUnit.SECONDS); passing an uncomputed/zero delay value to vertx.timer or APIs built on it (setTimer-like helpers, timeouts, debounce logic).
Common situations: A timeout constant initialized to 0 meaning 'no timeout' but passed to timer anyway; config value defaulted to 0; arithmetic producing a negative remaining-time (deadline already passed) fed into the timer.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Invalid null value passed for traffic shaping options update
- blockedThreadCheckInterval must be > 0
- maxEventLoopExecuteTime must be > 0
- maxWorkerpExecuteTime must be > 0
- internalBlockingPoolSize must be > 0
AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06).
Data as JSON: /api/errors/40efa1d67ef83c53.
Report an issue: GitHub.