alibaba/druid · warning · IllegalArgumentException

toCount can't not be less than zero

Error message

toCount can't not be less than zero

What it means

IllegalArgumentException thrown by fill(int toCount) when toCount is negative. fill() is meant to grow the pool to a target number of idle connections, so a negative target is a programmer error and is rejected before any physical connection is opened.

Source

Thrown at core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java:3818

        if (poolingCount == 0) {
            return null;
        }
        return getConnection();
    }

    @Override
    public int fill() throws SQLException {
        return this.fill(this.maxActive);
    }

    @Override
    public int fill(int toCount) throws SQLException {
        if (closed) {
            throw new DataSourceClosedException("dataSource already closed at " + new Date(closeTimeMillis));
        }

        if (toCount < 0) {
            throw new IllegalArgumentException("toCount can't not be less than zero");
        }

        init();

        if (toCount > this.maxActive) {
            toCount = this.maxActive;
        }

        int fillCount = 0;
        for (; ; ) {
            try {
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                connectErrorCountUpdater.incrementAndGet(this);
                throw new SQLException("interrupt", e);
            }

            boolean fillable = this.isFillable(toCount);

View on GitHub (pinned to fa8dc99126)

Solutions

  1. Clamp the computed toCount to at least 0 (or a sensible minimum) before calling fill().
  2. If you want 'fill to maxActive', call the no-arg fill() which does fill(this.maxActive) and never passes a negative.
  3. Validate configuration at startup: reject negative values for any pool-sizing property feeding fill().

Example fix

// before
int target = desiredIdle - extra;     // extra > desiredIdle -> target < 0
ddataSource.fill(target); // IllegalArgumentException

// after
ddataSource.fill(Math.max(0, target));
Defensive patterns

Strategy: validation

Validate before calling

if (toCount < 0) {
    throw new IllegalArgumentException("toCount must be >= 0, got " + toCount);
}
return dataSource.fill(Math.min(toCount, ((DruidDataSource) dataSource).getMaxActive()));

Prevention

When it happens

Trigger: dataSource.fill(-1) (or any toCount < 0) — the guard at line 3817 throws. Typically the result of a computed count underflowing to negative (e.g. maxActive - someDelta where delta > maxActive).

Common situations: Arithmetic producing a negative target (maxActive - headroom with headroom larger than maxActive); passing a config value that was unset and defaulted to -1; a unit test passing a sentinel; an off-by-one in a warm-up loop decrementing the target.

Related errors


AI-assisted analysis of alibaba/druid@fa8dc99126 (2026-08-14). Data as JSON: /api/errors/104af450228794b7. Report an issue: GitHub.