eclipse-vertx/vert.x · error · IllegalArgumentException

Timeout must be >= 0

Error message

Timeout must be >= 0

What it means

VertxConnection.shutdown(Duration) rejects negative durations with IllegalArgumentException ('Timeout must be >= 0'). The shutdown timeout bounds how long to wait for graceful close before force-closing the connection. Zero is allowed for immediate shutdown.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/net/impl/VertxConnection.java:186

    return shutdown(0L, TimeUnit.SECONDS);
  }

  /**
   * Calls {@link #shutdown(Duration)}
   */
  public final Future<Void> shutdown(long timeout, TimeUnit unit) {
    return shutdown(Duration.of(timeout, unit.toChronoUnit()));
  }

  /**
   * Initiate the connection shutdown sequence.
   *
   * @param timeout the shutdown timeout
   * @return the future completed after the channel's closure
   */
  public final Future<Void> shutdown(Duration timeout) {
    if (timeout.isNegative()) {
      throw new IllegalArgumentException("Timeout must be >= 0");
    }
    ChannelPromise promise = channel.newPromise();
    EventExecutor exec = chctx.executor();
    if (exec.inEventLoop()) {
      shutdown(timeout, promise);
    } else {
      exec.execute(() -> shutdown(timeout, promise));
    }
    PromiseInternal<Void> p = context.promise();
    promise.addListener(p);
    return p.future();
  }

  private void shutdown(Duration timeout, ChannelPromise promise) {
    if (shutdown != null) {
      ScheduledFuture<?> t = shutdownTimeout;
      if (timeout.isZero() && (t == null || t.cancel(false))) {
        shutdown = promise;

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Clamp: shutdown(Duration.ofSeconds(Math.max(0, seconds)))
  2. Handle expired deadlines explicitly by passing Duration.ZERO
  3. Fix config semantics so 'disabled' maps to a valid large duration, not a negative one

Example fix

// before
Duration remaining = deadline.minus(Instant.now());
conn.shutdown(remaining);
// after
Duration remaining = deadline.minus(Instant.now());
conn.shutdown(remaining.isNegative() ? Duration.ZERO : remaining);
Defensive patterns

Strategy: validation

Validate before calling

if (timeout != null && timeout.isNegative()) timeout = Duration.ZERO;

Try / catch

try {
  conn.shutdown(timeout);
} catch (IllegalArgumentException e) {
  conn.shutdown(Duration.ZERO);
}

Prevention

When it happens

Trigger: Calling connection.shutdown(Duration.ofMillis(-1)) or shutdown(someDuration) where the duration was computed as negative (e.g. deadline.minus(now) after the deadline passed).

Common situations: Passing a user config of -1 intending 'infinite', or computing remaining time as endTime - currentTime when already expired.

Understand the failure class

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/fe2585182eee9301. Report an issue: GitHub.