alibaba/druid · error · SQLException

Error

Error message

Error

What it means

Thrown by DruidPooledConnection.handleException(Throwable, String sql) when the passed Throwable is not a SQLException. After delegating to the DataSource's handleConnectionException, if the throwable is not a SQLException it is wrapped in SQLException("Error", t) so JDBC callers that only catch SQLException still receive it. Same wrapping rationale as error 45 but on the pooled-connection entry point.

Source

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

    public SQLException handleException(Throwable t) throws SQLException {
        return handleException(t, null);
    }

    public SQLException handleException(Throwable t, String sql) throws SQLException {
        final DruidConnectionHolder holder = this.holder;

        //
        if (holder != null) {
            DruidAbstractDataSource dataSource = holder.getDataSource();
            dataSource.handleConnectionException(this, t, sql);
        }

        if (t instanceof SQLException) {
            throw (SQLException) t;
        }

        throw new SQLException("Error", t);
    }

    public boolean isOracle() {
        return holder.getDataSource().isOracle();
    }

    public void closePoolableStatement(DruidPooledPreparedStatement stmt) throws SQLException {
        PreparedStatement rawStatement = stmt.stmt;

        final DruidConnectionHolder holder = this.holder;
        if (holder == null) {
            return;
        }

        if (stmt.pooled) {
            try {
                rawStatement.clearParameters();
            } catch (SQLException ex) {

View on GitHub (pinned to fa8dc99126)

Solutions

  1. Read getCause() for the original non-SQL Throwable and fix its root cause.
  2. Make custom interceptors/Filters throw SQLException so they propagate as typed SQL failures.
  3. Treat a non-SQLException here as a serious condition (often an Error) warranting request failure and logging at ERROR.

Example fix

// before
pooledConn.handleException(new RuntimeException("driver bug"));

// after — wrap upstream failures in SQLException
pooledConn.handleException(new SQLException("driver bug", runtimeEx));
Defensive patterns

Strategy: try-catch

Validate before calling

if (!(t instanceof SQLException)) {
    // wrap upstream so handleException sees a typed SQL exception
    t = new SQLException("wrapped non-SQL failure", t);
}
pooledConn.handleException(t);

Type guard

boolean isSqlOrWrapped = (t instanceof SQLException)
    || (t.getCause() instanceof SQLException);

Try / catch

try {
    pooledConn.handleException(t);
} catch (SQLException e) {
    if ("Error".equals(e.getMessage()) && !(e.getCause() instanceof SQLException)) {
        Throwable real = e.getCause();
        log.error("non-SQL throwable in pooled connection", real);
        if (real instanceof Error) throw (Error) real;
    }
    throw e;
}

Prevention

When it happens

Trigger: pooledConn.handleException(someError) where someError is e.g. a RuntimeException or java.lang.Error thrown by a custom statement interceptor, a driver bug, or a Filter. Line 131 wraps it.

Common situations: A Filter or statement proxy throwing a non-SQL exception that bubbles into handleException; OOM/StackOverflow during statement use; a third-party JDBC wrapper raising RuntimeExceptions; misbehaving driver raising Error on closed resources.

Related errors


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