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
- Inspect the chained disableError to find the underlying failure (validation query failed, fatal SQL state) and fix the DB/network side.
- Discard the disabled connection reference and borrow a fresh one (try-with-resources ensures this).
- 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
- Inspect the chained disableError to find the validation/fatal failure and fix the DB side.
- Tune testWhileIdle / validationQuery so bad connections are discarded before handout.
- Always borrow a fresh connection after a disabled one; never try to revive it.
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
- connection closed
- validationQuery didn't return a row
- onFatalError, activeCount {}, onFatalErrorMaxActive {}
- wait millis {waitMillis}, active {activeCount}, maxActive {m
- maxEvictableIdleTimeMillis must be grater than minEvictableI
AI-assisted analysis of alibaba/druid@fa8dc99126 (2026-08-14).
Data as JSON: /api/errors/8c8ad5bf15b14b6f.
Report an issue: GitHub.