{"record":{"id":"e2ee7204fb0c8ffe","repo":"alibaba/druid","slug":"minidle-greater-than-maxactive-must","errorCode":null,"errorMessage":"minIdle greater than maxActive, {} must >= {}","messagePattern":"minIdle greater than maxActive, (.+?) must >= (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java","lineNumber":1125,"sourceCode":"    public int getNotFullTimeoutRetryCount() {\n        return notFullTimeoutRetryCount;\n    }\n\n    public void setNotFullTimeoutRetryCount(int notFullTimeoutRetryCount) {\n        this.notFullTimeoutRetryCount = notFullTimeoutRetryCount;\n    }\n\n    public int getMinIdle() {\n        return minIdle;\n    }\n\n    public void setMinIdle(int value) {\n        if (value == this.minIdle) {\n            return;\n        }\n\n        if (inited && value > this.maxActive) {\n            throw new IllegalArgumentException(\"minIdle greater than maxActive, \" + maxActive + \" must >= \" + this.minIdle);\n        }\n\n        if (minIdle < 0) {\n            throw new IllegalArgumentException(\"minIdle must >= 0\");\n        }\n\n        this.minIdle = value;\n    }\n\n    public int getMaxIdle() {\n        return maxIdle;\n    }\n\n    @Deprecated\n    public void setMaxIdle(int maxIdle) {\n        LOG.error(\"maxIdle is deprecated\");\n        this.maxIdle = maxIdle;\n    }","sourceCodeStart":1107,"sourceCodeEnd":1143,"githubUrl":"https://github.com/alibaba/druid/blob/fa8dc9912637a2f729eef9f55356621fec18d40e/core/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java#L1107-L1143","documentation":"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.","triggerScenarios":"Post-init call to setMinIdle(value) where value > ds.getMaxActive().","commonSituations":"Runtime resize where maxActive was lowered but minIdle was not adjusted first; config reload setting minIdle from a source whose value exceeds maxActive.","solutions":["Ensure minIdle <= maxActive at all times (and ideally minIdle <= maxIdle).","When lowering maxActive at runtime, lower minIdle first.","Read getMaxActive() before calling setMinIdle to compute a safe value."],"exampleFix":"// before (post-init)\n// ds.setMinIdle(20); // maxActive is 10 -> throws\n\n// after\n// int safe = Math.min(20, ds.getMaxActive());\n// ds.setMinIdle(safe);","handlingStrategy":"validation","validationCode":"int v = desiredMinIdle;\nif (ds.isInited() && v > ds.getMaxActive()) {\n    v = ds.getMaxActive(); // clamp, or raise maxActive first\n}\nds.setMinIdle(v);","typeGuard":null,"tryCatchPattern":"try {\n    ds.setMinIdle(value);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"minIdle greater than maxActive\")) {\n        // lower value to <= maxActive, or raise maxActive first\n    }\n    throw e;\n}","preventionTips":["Keep minIdle <= maxActive always (and ideally <= maxIdle).","When lowering maxActive at runtime, lower minIdle first.","Read getMaxActive() before computing the new minIdle."],"tags":["datasource","pool-sizing","validation","configuration"],"backgroundTag":null,"analyzedSha":"fa8dc9912637a2f729eef9f55356621fec18d40e","analyzedAt":"2026-08-14T04:55:06.789Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}