eclipse-vertx/vert.x · error · IllegalArgumentException

Timeout must be >= 0

Error message

Timeout must be >= 0

What it means

Http3Connection.shutdown(Duration) validates that the shutdown timeout is not negative before delegating to the QUIC connection shutdown. A negative Duration is meaningless for a timeout, so IllegalArgumentException is thrown immediately.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/http3/Http3Connection.java:269

            vSetting = Http3Settings.MAX_FIELD_SECTION_SIZE;
            break;
          default:
            continue;
        }
        vSettings.setLong(vSetting, setting.getValue());
      }
    }
    remoteSettings = vSettings;
    Handler<HttpSettings> handler = remoteSettingsHandler;
    if (handler != null) {
      context.dispatch(vSettings, handler);
    }
  }

  @Override
  public Future<Void> shutdown(Duration timeout) {
    if (timeout.isNegative()) {
      throw new IllegalArgumentException("Timeout must be >= 0");
    }
    return connection.shutdown(timeout);
  }

  private void handleShutdown(QuicStreamChannel localControlStream, Duration timeout) {
    localGoAway = mostRecentRemoteStreamId + 4;
    PromiseInternal<Void> p = context.promise();
    if (remoteGoAway == -1L) {
      Handler<Void> handler = shutdownHandler;
      if (handler != null) {
        context.emit(null, handler);
      }
    }
    sendGoAway(localControlStream, mostRecentRemoteStreamId + 4, p);
  }

  private void handleGrace(QuicStreamChannel localControlStream) {
    if (localGoAway == -1L || localGoAway > 0L) {

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Pass a zero or positive Duration, e.g. Duration.ZERO or Duration.ofSeconds(30).
  2. Clamp: Duration t = timeout.isNegative() ? Duration.ZERO : timeout.
  3. Use a null or a dedicated method if the API offers one for indefinite shutdown, instead of a negative sentinel.

Example fix

// before
conn.shutdown(Duration.ofSeconds(-1));
// after
conn.shutdown(Duration.ofSeconds(30));
Defensive patterns

Strategy: validation

Validate before calling

if (timeout == null || timeout.isNegative()) throw new IllegalArgumentException("timeout must be >= 0");

Type guard

boolean isValidShutdownTimeout(Duration d) { return d != null && !d.isNegative(); }

Try / catch

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

Prevention

When it happens

Trigger: Calling shutdown(Duration.ofSeconds(-1)) or any negative duration, e.g. from misparsed configuration ('-1' meaning infinite) or an arithmetic result that went negative.

Common situations: Using -1 as an 'infinite/disabled' sentinel from other frameworks' conventions; subtracting deadlines producing negative Durations; config placeholders not replaced (e.g. ${timeout} parsed badly).

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


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