{"record":{"id":"aa21826760fa0c39","repo":"eclipse-vertx/vert.x","slug":"cannot-schedule-a-timer-with-initialdelay-0","errorCode":null,"errorMessage":"Cannot schedule a timer with initialDelay < 0","messagePattern":"Cannot schedule a timer with initialDelay < 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java","lineNumber":693,"sourceCode":"      options = new DnsClientOptions(options)\n      .setHost(address.getAddress().getHostAddress())\n      .setPort(address.getPort());\n    }\n    return new DnsClientImpl(this, options);\n  }\n\n  private long scheduleTimeout(ContextInternal context,\n                              boolean periodic,\n                              long initialDelay,\n                              long delay,\n                              TimeUnit timeUnit,\n                              boolean addCloseHook,\n                              Handler<Long> handler) {\n    if (delay < 1) {\n      throw new IllegalArgumentException(\"Cannot schedule a timer with delay < 1 ms\");\n    }\n    if (initialDelay < 0) {\n      throw new IllegalArgumentException(\"Cannot schedule a timer with initialDelay < 0\");\n    }\n    long timerId = timeoutCounter.getAndIncrement();\n    InternalTimerHandler task = new InternalTimerHandler(timerId, handler, periodic, context);\n    timeouts.put(timerId, task);\n    if (addCloseHook) {\n      context.addCloseHook(task);\n    }\n    EventLoop el = context.nettyEventLoop();\n    if (periodic) {\n      task.future = el.scheduleAtFixedRate(task, initialDelay, delay, timeUnit);\n    } else {\n      task.future = el.schedule(task, delay, timeUnit);\n    }\n    return task.id;\n  }\n\n  public long scheduleTimeout(ContextInternal context,\n                                              boolean periodic,","sourceCodeStart":675,"sourceCodeEnd":711,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java#L675-L711","documentation":"Vert.x validates the initialDelay parameter of periodic timer scheduling and throws IllegalArgumentException when it is negative. A negative initial delay has no meaning in the underlying scheduler, so it is rejected before the timer is registered. Note delay itself must also be >= 1 ms (separate check).","triggerScenarios":"vertx.setPeriodic(initialDelay, delay, unit, handler) or the InternalTimerHandler scheduling path with initialDelay < 0, typically from a config-computed value like (deadline - now).","commonSituations":"Computing an initial delay from timestamps where the deadline already passed (now > deadline yields negative); misordered subtraction (deadline - now vs now - deadline); negative config values.","solutions":["Clamp: initialDelay = Math.max(0, computedInitialDelay) before calling setPeriodic","Fix the subtraction order so delay = deadline - now, and skip scheduling when the deadline already passed","Validate the config value at load time and reject/normalize negatives early"],"exampleFix":"// before\nlong initial = deadline - System.currentTimeMillis();\nvertx.setPeriodic(initial, 1000, TimeUnit.MILLISECONDS, h -> tick()); // negative if deadline passed\n// after\nlong initial = Math.max(0, deadline - System.currentTimeMillis());\nvertx.setPeriodic(initial, 1000, TimeUnit.MILLISECONDS, h -> tick());","handlingStrategy":"validation","validationCode":"if (initialDelayMs < 0) {\n  initialDelayMs = 0; // or skip scheduling\n}","typeGuard":null,"tryCatchPattern":"try {\n  vertx.setPeriodic(initialDelayMs, periodMs, TimeUnit.MILLISECONDS, handler);\n} catch (IllegalArgumentException e) {\n  // normalize initialDelay and retry once\n}","preventionTips":["Clamp timestamp-derived delays with Math.max(0, deadline - now)","Verify subtraction order when computing delays","Validate negative timer config at load time"],"tags":["timer","scheduling","argument-validation"],"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"}