{"record":{"id":"6d7198b947710a19","repo":"eclipse-vertx/vert.x","slug":"cannot-schedule-a-timer-with-delay-1-ms","errorCode":null,"errorMessage":"Cannot schedule a timer with delay < 1 ms","messagePattern":"Cannot schedule a timer with delay < 1 ms","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java","lineNumber":690,"sourceCode":"      DnsAddressResolverProvider provider = DnsAddressResolverProvider.create(this, addressResolverOptions);\n      InetSocketAddress address = provider.nameServerAddresses().get(0);\n      // provide the host and port\n      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  }","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/impl/VertxImpl.java#L672-L708","documentation":"Vert.x rejects timer scheduling when the delay (or period) is less than 1 millisecond. Internally timers map onto Netty HashedWheelTimer/EventLoop schedules which cannot honor sub-millisecond periods, so scheduleTimer validates delay >= 1 before creating the InternalTimerHandler. The error is an IllegalArgumentException thrown synchronously on the calling thread.","triggerScenarios":"vertx.setTimer(0, handler), vertx.setPeriodic(0, handler), or any periodic scheduling whose delay parameter is 0 or negative, including through setPeriodic(initialDelay, delay, unit, handler) with delay < 1 in the given TimeUnit.","commonSituations":"Passing a config value of 0 meaning 'no delay' or 'disabled'; converting from another unit where rounding yields 0 (e.g. 500 microseconds to ms); defaulting an unset config to 0; a busy-poll retry loop intended to run immediately.","solutions":["Use a delay of at least 1 ms, e.g. Math.max(1, configuredDelay)","To run as soon as possible, use vertx.runOnContext(handler) instead of a 0-delay timer","Guard config-derived values before scheduling: if (delayMs < 1) delayMs = 1; or skip scheduling entirely","Check unit conversion: sub-millisecond intervals are unsupported; pick a different mechanism"],"exampleFix":"// before\nvertx.setPeriodic(0, id -> poll()); // IllegalArgumentException\n// after\nvertx.runOnContext(v -> poll()); // immediate\nvertx.setPeriodic(Math.max(1, configuredDelayMs), id -> poll());","handlingStrategy":"validation","validationCode":"if (delayMs < 1) {\n  throw new IllegalArgumentException(\"delay must be >= 1 ms, got \" + delayMs);\n}","typeGuard":null,"tryCatchPattern":"try {\n  vertx.setPeriodic(delayMs, handler);\n} catch (IllegalArgumentException e) {\n  // fall back to minimum delay or immediate runOnContext\n}","preventionTips":["Clamp config-derived delays with Math.max(1, delay)","Use vertx.runOnContext for immediate execution instead of 0 delay","Check unit conversions that can truncate to 0"],"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-14T05:17:10.506Z"}