{"record":{"id":"40efa1d67ef83c53","repo":"eclipse-vertx/vert.x","slug":"invalid-timer-delay-delay","errorCode":null,"errorMessage":"Invalid timer delay: ${delay}","messagePattern":"Invalid timer delay: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/internal/ContextInternal.java","lineNumber":428,"sourceCode":"   * Like {@link #timer(long, TimeUnit)} with a unit in millis.\n   */\n  default Timer timer(long delay) {\n    return timer(delay, TimeUnit.MILLISECONDS);\n  }\n\n  /**\n   * Create a timer task configured with the specified {@code delay}, when the timeout fires the timer future\n   * is succeeded, when the timeout is cancelled the timer future is failed with a {@link java.util.concurrent.CancellationException}\n   * instance.\n   *\n   * @param delay the delay\n   * @param unit the delay unit\n   * @return the timer object\n   */\n  default Timer timer(long delay, TimeUnit unit) {\n    Objects.requireNonNull(unit);\n    if (delay <= 0) {\n      throw new IllegalArgumentException(\"Invalid timer delay: \" + delay);\n    }\n    io.netty.util.concurrent.ScheduledFuture<Void> fut = nettyEventLoop().schedule(() -> null, delay, unit);\n    TimerImpl timer = new TimerImpl(this, fut);\n    fut.addListener(timer);\n    return timer;\n  }\n\n  /**\n   * @return {@code true} when the context is associated with a deployment\n   */\n  default boolean isDeployment() {\n    return deployment() != null;\n  }\n\n  default int getInstanceCount() {\n    DeploymentContext deployment = deployment();\n    if (deployment == null) {\n      return 0;","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/internal/ContextInternal.java#L410-L446","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nctx.timer(timeoutMs, TimeUnit.MILLISECONDS);\n// after\nif (timeoutMs <= 0) {\n  handleTimeoutNow();\n} else {\n  ctx.timer(timeoutMs, TimeUnit.MILLISECONDS);\n}","handlingStrategy":"validation","validationCode":"if (delay <= 0) throw new IllegalArgumentException(\"timer delay must be > 0, got \" + delay);","typeGuard":null,"tryCatchPattern":"try { t = ctx.timer(delay, unit); } catch (IllegalArgumentException e) { handleImmediateTimeout(); }","preventionTips":["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"],"tags":["timer","illegal-argument","vertx"],"backgroundTag":"invalid-argument-value","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}