alibaba/druid · error · SQLException
keepAliveBetweenTimeMillis must be greater than timeBetweenE
Error message
keepAliveBetweenTimeMillis must be greater than timeBetweenEvictionRunsMillis
What it means
SQLException thrown during init() when keepAlive is enabled and keepAliveBetweenTimeMillis <= timeBetweenEvictionRunsMillis. The keepAlive ping is meant to run only on connections idle longer than keepAliveBetweenTimeMillis; if that threshold is not greater than the evictor's run interval, the keepAlive cadence becomes meaningless or harmful, so Druid rejects it.
Source
Thrown at core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java:739
if (maxActive < minIdle) {
throw new IllegalArgumentException("illegal maxActive " + maxActive);
}
if (getInitialSize() > maxActive) {
throw new IllegalArgumentException("illegal initialSize " + this.initialSize + ", maxActive " + maxActive);
}
if (timeBetweenLogStatsMillis > 0 && useGlobalDataSourceStat) {
throw new IllegalArgumentException("timeBetweenLogStatsMillis not support useGlobalDataSourceStat=true");
}
if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
}
if (keepAlive && keepAliveBetweenTimeMillis <= timeBetweenEvictionRunsMillis) {
throw new SQLException("keepAliveBetweenTimeMillis must be greater than timeBetweenEvictionRunsMillis");
}
if (this.driverClass != null) {
this.driverClass = driverClass.trim();
}
initFromSPIServiceLoader();
resolveDriver();
initCheck();
this.netTimeoutExecutor = new SynchronousExecutor();
initExceptionSorter();
initValidConnectionChecker();
validationQueryCheck();
View on GitHub (pinned to fa8dc99126)
Solutions
- Set keepAliveBetweenTimeMillis to a value strictly greater than timeBetweenEvictionRunsMillis (commonly 2x or more).
- Confirm units are milliseconds for both.
- If you do not need keepAlive, leave keepAlive=false to avoid the constraint entirely.
Example fix
// before dataSource.setKeepAlive(true); dataSource.setTimeBetweenEvictionRunsMillis(60_000); dataSource.setKeepAliveBetweenTimeMillis(60_000); // not greater -> throws // after dataSource.setKeepAlive(true); dataSource.setTimeBetweenEvictionRunsMillis(60_000); dataSource.setKeepAliveBetweenTimeMillis(120_000);
Defensive patterns
Strategy: validation
Validate before calling
if (dataSource.isKeepAlive()
&& dataSource.getKeepAliveBetweenTimeMillis() <= dataSource.getTimeBetweenEvictionRunsMillis()) {
throw new IllegalStateException("keepAliveBetweenTimeMillis must be > timeBetweenEvictionRunsMillis");
} Prevention
- When enabling keepAlive, set keepAliveBetweenTimeMillis above the eviction interval.
- Re-validate timing config after changing either value.
- Disable keepAlive if you do not need idle-ping behavior.
When it happens
Trigger: init() with keepAlive=true and keepAliveBetweenTimeMillis <= timeBetweenEvictionRunsMillis. The check at line 738 throws.
Common situations: Enabling keepAlive without raising keepAliveBetweenTimeMillis above the eviction interval; tightening timeBetweenEvictionRunsMillis for aggressive eviction while keepAlive is on; defaults misaligned after enabling keepAlive.
Related errors
- maxEvictableIdleTimeMillis must be grater than minEvictableI
- validationQuery didn't return a row
- illegal maxActive {}
- illegal initialSize {}, maxActive {}
- timeBetweenLogStatsMillis not support useGlobalDataSourceSta
AI-assisted analysis of alibaba/druid@fa8dc99126 (2026-08-14).
Data as JSON: /api/errors/1eebe93bd5b98eee.
Report an issue: GitHub.