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
- Clamp the computed toCount to at least 0 (or a sensible minimum) before calling fill().
- If you want 'fill to maxActive', call the no-arg fill() which does fill(this.maxActive) and never passes a negative.
- 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
- Clamp computed fill targets with Math.max(0, x).
- Prefer the no-arg fill() which uses maxActive and can never be negative.
- Validate pool-sizing config at startup.
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
- logger can not be null
- validationQuery didn't return a row
- maxActive less than minIdle, {} < {}
- maxActive can't not set zero
- illegal maxActive {}
AI-assisted analysis of alibaba/druid@fa8dc99126 (2026-08-14).
Data as JSON: /api/errors/104af450228794b7.
Report an issue: GitHub.