alibaba/druid · error · SQLException

interrupt

Error message

interrupt

What it means

SQLException('interrupt') wrapping InterruptedException, thrown by init() when the thread waiting to acquire the init lock (lock.lockInterruptibly()) is interrupted before it obtains the lock. Druid prefers to surface the interruption as a checked SQLException rather than reset the interrupt flag silently.

Source

Thrown at core/src/main/java/com/alibaba/druid/pool/DruidDataSource.java:671

            }
        }

        this.connectProperties = properties;
    }

    public void init() throws SQLException {
        if (inited) {
            return;
        }

        // bug fixed for dead lock, for issue #2980
        DruidDriver.getInstance();

        final ReentrantLock lock = this.lock;
        try {
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            throw new SQLException("interrupt", e);
        }

        boolean init = false;
        try {
            if (inited) {
                return;
            }

            initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());

            this.id = DruidDriver.createDataSourceId();
            if (this.id > 1) {
                long delta = (this.id - 1) * 100000;
                connectionIdSeedUpdater.addAndGet(this, delta);
                statementIdSeedUpdater.addAndGet(this, delta);
                resultSetIdSeedUpdater.addAndGet(this, delta);
                transactionIdSeedUpdater.addAndGet(this, delta);
            }

View on GitHub (pinned to fa8dc99126)

Solutions

  1. Ensure the thread performing init()/first getConnection() is not interrupted during startup; defer shutdown signals until init completes.
  2. If interruption is expected (e.g. bounded startup), catch SQLException and check getCause() instanceof InterruptedException, then retry init on a non-interrupted thread.
  3. Call init() eagerly during a controlled startup phase rather than lazily on the request path.

Example fix

// before
executor.submit(() -> dataSource.init()).get(2, TimeUnit.SECONDS); // may interrupt
// after
Thread t = new Thread(() -> { try { dataSource.init(); } catch (SQLException e) { /* log */ } });
t.start();
t.join(); // do not interrupt during init
Defensive patterns

Strategy: try-catch

Validate before calling

if (Thread.currentThread().isInterrupted()) {
    Thread.interrupted(); // clear flag
    LOG.warn("init thread was interrupted; clearing and proceeding");
}

Try / catch

try {
    dataSource.init();
} catch (SQLException e) {
    if ("interrupt".equals(e.getMessage()) && e.getCause() instanceof InterruptedException) {
        // re-run init on a fresh, non-interrupted thread
        throw new IllegalStateException("datasource init interrupted", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Thread calling dataSource.init() (or the first getConnection() that triggers lazy init) is interrupted via Thread.interrupt() while blocked on this.lock.lockInterruptibly() at line 665. The catch at 669 wraps and throws.

Common situations: Application shutdown interrupting threads mid-startup; a thread pool / executor shutting down tasks during datasource init; a watchdog or timeout framework interrupting the init thread; reusing interrupted threads.

Related errors


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