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

  1. Set keepAliveBetweenTimeMillis to a value strictly greater than timeBetweenEvictionRunsMillis (commonly 2x or more).
  2. Confirm units are milliseconds for both.
  3. 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 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


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