alibaba/druid · warning · IllegalArgumentException

minIdle must >= 0

Error message

minIdle must >= 0

What it means

setMinIdle contains a guard intended to reject negative values, but it checks the FIELD 'minIdle' (the old value) instead of the parameter 'value'. Because the field defaults to 0 and is only ever assigned through this setter, the check is effectively inert for detecting a newly-supplied negative value. Treat this message as evidence of an already-negative field (e.g. set via reflection or an inconsistent state) rather than a reliable guard against bad input.

Source

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

    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;
    }

    public int getInitialSize() {
        return initialSize;
    }

View on GitHub (pinned to fa8dc99126)

Solutions

  1. Do not rely on this setter to validate negative input - pre-validate the value yourself.
  2. If you observe this error, find where the minIdle field was set negative (reflection, deserialization) and correct it.
  3. Validate minIdle >= 0 before calling setMinIdle.

Example fix

// before
// ds.setMinIdle(-5); // NOT caught by this (buggy) guard

// after - validate yourself
// if (value < 0) throw new IllegalArgumentException("minIdle must >= 0");
// ds.setMinIdle(value);
Defensive patterns

Strategy: validation

Validate before calling

int v = desiredMinIdle;
if (v < 0) throw new IllegalArgumentException("minIdle must >= 0");
// self-validate, because the setter's guard checks the OLD field, not the new value
ds.setMinIdle(v);

Try / catch

try {
    ds.setMinIdle(value);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("minIdle must >= 0")) {
        // the field was already negative (reflection/deserialization); reconstruct the datasource cleanly
    }
    throw e;
}

Prevention

When it happens

Trigger: The branch fires only when this.minIdle (the existing field) is already < 0 at the time of a setMinIdle call - which normally cannot happen through the setter itself.

Common situations: Reflection/unsafe mutation left the minIdle field negative; a deserialized/reconstructed datasource object with an inconsistent field; essentially a defensive check that does not fire for the input you would expect.

Related errors


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