quarkusio/quarkus · error · java.lang.IllegalArgumentException

Duration cannot be negative.

Error message

Duration cannot be negative.

What it means

UnitisedTime.unitised() converts a java.time.Duration into a (value, TimeUnit) pair for Vert.x pool options. Negative durations are invalid for pool timeouts, so it throws IllegalArgumentException early instead of passing a nonsensical negative timeout to the client.

Source

Thrown at extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/UnitisedTime.java:26

    public final int value;
    public final TimeUnit unit;

    public UnitisedTime(int value, TimeUnit unit) {
        this.value = value;
        this.unit = unit;
    }

    /**
     * Convert a {@link Duration} to a {@link UnitisedTime} with the smallest possible
     * {@link TimeUnit} starting from {@link TimeUnit#MILLISECONDS}.
     *
     * @param duration Duration to convert
     *
     * @return UnitisedTime
     */
    public static UnitisedTime unitised(Duration duration) {
        if (duration.isNegative()) {
            throw new IllegalArgumentException("Duration cannot be negative.");
        }

        long millis = duration.toMillis();
        if (millis < Integer.MAX_VALUE) {
            return new UnitisedTime((int) millis, TimeUnit.MILLISECONDS);
        }

        long seconds = duration.getSeconds();
        if (seconds < Integer.MAX_VALUE) {
            return new UnitisedTime((int) seconds, TimeUnit.SECONDS);
        }

        long minutes = duration.toMinutes();
        if (minutes < Integer.MAX_VALUE) {
            return new UnitisedTime((int) minutes, TimeUnit.MINUTES);
        }

        long hours = duration.toHours();

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set the offending quarkus.datasource."<name>".reactive.<timeout> property to zero or a positive duration
  2. Use Duration.ZERO or remove the property to rely on defaults — never a negative value
  3. In programmatic use, validate Duration arguments before calling UnitisedTime.unitised()

Example fix

// before
quarkus.datasource.db.reactive.connect-timeout=-1s
// after
quarkus.datasource.db.reactive.connect-timeout=5s
Defensive patterns

Strategy: validation

Validate before calling

if (duration != null && duration.isNegative()) {
    throw new IllegalArgumentException("Timeout must be >= 0: " + duration);
}
UnitisedTime t = UnitisedTime.unitised(duration);

Try / catch

try {
    UnitisedTime t = UnitisedTime.unitised(duration);
} catch (IllegalArgumentException e) {
    duration = Duration.ZERO; // or a sensible default
}

Prevention

When it happens

Trigger: Passing a negative Duration (e.g. Duration.ofSeconds(-1)) to unitised(), which happens when reactive pool timeout configs such as connect-timeout or idle-timeout are set to a negative value.

Common situations: Misreading a config option as 'disabled by negative value'; unit mistakes like -1 in quarkus.datasource."x".reactive.connect-timeout; building runtime config programmatically with a sentinel -1.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/a2144589c5ffa11a. Report an issue: GitHub.