apache/shardingsphere · warning · SQLWrapperException

5

5

Error message

Underlying SQL state: %s, underlying error code: %s.

What it means

Thrown as SQLWrapperException when closing a group of DataSources and one or more close() calls fail with SQLException. The wrapper chains every underlying failure via SQLException.setNextException, and its message template reports the underlying SQL state and error code so callers can see which driver/database actually failed. It is a shutdown-time aggregation error: the original causes are preserved in the chain, not swallowed.

Source

Thrown at infra/util/src/main/java/org/apache/shardingsphere/infra/util/close/DataSourcesCloser.java:63

                    ((AutoCloseable) each).close();
                    // CHECKSTYLE:OFF
                } catch (final Exception ex) {
                    // CHECKSTYLE:ON
                    causes.add(ex);
                }
            }
        }
        if (!causes.isEmpty()) {
            throwException(causes);
        }
    }
    
    private static void throwException(final Collection<Exception> causes) {
        SQLException sqlException = new SQLException("");
        for (Exception each : causes) {
            sqlException.setNextException(new SQLException(each));
        }
        throw new SQLWrapperException(sqlException);
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Inspect the wrapped exception chain via getNextException() on the SQLWrapperException to find the real SQLState/vendor code of the failing datasource.
  2. Ensure connections/statements are closed by application code before container shutdown invokes datasource close.
  3. If the error is transient (DB restarted), verify the database is reachable and retry the shutdown/close sequence.
  4. If a specific datasource is misconfigured (wrong URL, expired credentials), fix its configuration so close() no longer fails.

Example fix

// before
catch (final SQLException ex) {
    throw new SQLWrapperException(sqlException);
}
// caller: inspect chain
// after
catch (final SQLWrapperException ex) {
    SQLException next = ex.getNextException();
    while (next != null) {
        LOG.error("close failed: state={}, code={}", next.getSQLState(), next.getErrorCode(), next);
        next = next.getNextException();
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before teardown: verify pools are idle
for (DataSource ds : pools) { /* drain/quiet app queries first */ }

Try / catch

catch (final SQLWrapperException ex) { for (SQLException n = ex.getNextException(); n != null; n = n.getNextException()) { log("state={} code={}", n.getSQLState(), n.getErrorCode()); } }

Prevention

When it happens

Trigger: Calling DataSourcesCloser.close (or any path that closes multiple pooled DataSources, e.g. datasource teardown on application shutdown) where at least one underlying JDBC DataSource.close() throws a SQLException; the collected causes are wrapped and rethrown.

Common situations: Application shutdown while connections are still in flight; connection pools (HikariCP/DBCP) already invalidated or their DB unreachable at close time; closing a datasource that failed mid-initialization; double-closing datasources in a context-destroy callback.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/5da38285cf119516. Report an issue: GitHub.