alibaba/druid · error · IllegalArgumentException

minIdle greater than maxActive, {} must >= {}

Error message

minIdle greater than maxActive, {} must >= {}

What it means

After the pool is initialized, setMinIdle rejects any value greater than the current maxActive. Be aware the interpolated message is misleading: it reads 'minIdle greater than maxActive, <maxActive> must >= <oldMinIdle>' but the actual guard is on the NEW value vs maxActive. The condition is correct; only the message text is confusing.

Source

Thrown at core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java:1125

    public int getNotFullTimeoutRetryCount() {
        return notFullTimeoutRetryCount;
    }

    public void setNotFullTimeoutRetryCount(int notFullTimeoutRetryCount) {
        this.notFullTimeoutRetryCount = notFullTimeoutRetryCount;
    }

    public int getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(int value) {
        if (value == this.minIdle) {
            return;
        }

        if (inited && value > this.maxActive) {
            throw new IllegalArgumentException("minIdle greater than maxActive, " + maxActive + " must >= " + this.minIdle);
        }

        if (minIdle < 0) {
            throw new IllegalArgumentException("minIdle must >= 0");
        }

        this.minIdle = value;
    }

    public int getMaxIdle() {
        return maxIdle;
    }

    @Deprecated
    public void setMaxIdle(int maxIdle) {
        LOG.error("maxIdle is deprecated");
        this.maxIdle = maxIdle;
    }

View on GitHub (pinned to fa8dc99126)

Solutions

  1. Ensure minIdle <= maxActive at all times (and ideally minIdle <= maxIdle).
  2. When lowering maxActive at runtime, lower minIdle first.
  3. Read getMaxActive() before calling setMinIdle to compute a safe value.

Example fix

// before (post-init)
// ds.setMinIdle(20); // maxActive is 10 -> throws

// after
// int safe = Math.min(20, ds.getMaxActive());
// ds.setMinIdle(safe);
Defensive patterns

Strategy: validation

Validate before calling

int v = desiredMinIdle;
if (ds.isInited() && v > ds.getMaxActive()) {
    v = ds.getMaxActive(); // clamp, or raise maxActive first
}
ds.setMinIdle(v);

Try / catch

try {
    ds.setMinIdle(value);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("minIdle greater than maxActive")) {
        // lower value to <= maxActive, or raise maxActive first
    }
    throw e;
}

Prevention

When it happens

Trigger: Post-init call to setMinIdle(value) where value > ds.getMaxActive().

Common situations: Runtime resize where maxActive was lowered but minIdle was not adjusted first; config reload setting minIdle from a source whose value exceeds maxActive.

Related errors


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