alibaba/druid · error · SQLException

connection disabled

Error message

connection disabled

What it means

Thrown by DruidPooledConnection.checkStateInternal() when the connection is disabled (disable flag true) AND a disableError is set. 'Disabled' means Druid has taken the connection out of use due to a detected problem but the chained disableError explains why — typically a fatal/validated error that did not also set closed.

Source

Thrown at core/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java:1184

                lock.unlock();
            }
        } else {
            checkStateInternal();
        }
    }

    private void checkStateInternal() throws SQLException {
        if (closed) {
            if (disableError != null) {
                throw new SQLException("connection closed", disableError);
            } else {
                throw new SQLException("connection closed");
            }
        }

        if (disable) {
            if (disableError != null) {
                throw new SQLException("connection disabled", disableError);
            } else {
                throw new SQLException("connection disabled");
            }
        }

        if (holder == null) {
            if (disableError != null) {
                throw new SQLException("connection holder is null", disableError);
            } else {
                throw new SQLException("connection holder is null");
            }
        }
    }

    public String toString() {
        if (conn != null) {
            return conn.toString();
        } else {

View on GitHub (pinned to fa8dc99126)

Solutions

  1. Inspect the chained disableError to find the underlying failure (validation query failed, fatal SQL state) and fix the DB/network side.
  2. Discard the disabled connection reference and borrow a fresh one (try-with-resources ensures this).
  3. Tune validation (validationQuery, testWhileIdle, testOnBorrow) so bad connections are detected and discarded before handout.

Example fix

// before
Connection c = dataSource.getConnection();
// ... fatal error disables c ...
c.createStatement(); // SQLException("connection disabled", disableError)

// after
try (Connection c = dataSource.getConnection()) {
    use(c);
} catch (SQLException e) {
    // borrow a fresh connection on retry; the disabled one is gone
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (pooledConn.isDisable()) {
    Throwable why = pooledConn.getDisableError();
    throw new IllegalStateException("connection disabled" + (why == null ? "" : ": " + why));
}
// proceed

Type guard

boolean usable = pooledConn != null && !pooledConn.isDisable() && !pooledConn.isClosed();

Try / catch

try {
    pooledConn.createStatement();
} catch (SQLException e) {
    if ("connection disabled".equals(e.getMessage()) && e.getCause() != null) {
        log.error("conn disabled by Druid due to: {}", e.getCause());
        borrowFreshAndRetry();
    } else throw e;
}

Prevention

When it happens

Trigger: JDBC operation on a DruidPooledConnection whose disable flag is true and disableError != null; closed flag is false so it falls through to the disable branch at line 1183. The connection was disabled (e.g. by a validation failure or fatal error detected on the physical connection) but not yet closed.

Common situations: Connection failed keep-alive/validation and was disabled; a fatal error was detected and handleConnectionException disabled it; the pool's testWhileIdle marked the connection bad; using a connection after it was disabled but before/as it is being discarded.

Related errors


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