apache/seatunnel · warning
unable to close XA connection
Error message
unable to close XA connection
What it means
A WARN log in XaFacadeImplAutoLoad.close() when closing the underlying XA connection throws a SQLException. The resource is still discarded (xaResource nulled) even though the close failed; this is logged to flag a potential connection leak on the database side while not failing the job. Recovery: the connection object remains referenced by the JDBC driver until GC; some DBs may leak XA resources.
Solutions
- Verify network/firewall idle timeouts exceed checkpoint interval; enable TCP keepalive on the DB connection
- Check DB-side session limits and stale-connection cleanup (e.g. wait_timeout in MySQL)
- If leaks accumulate, restart the task or recycle the DataSource; this warning is otherwise safe to ignore at shutdown
- Upgrade the JDBC driver if a known close-after-XA bug applies
Defensive patterns
Strategy: try-catch
Validate before calling
// Before shutdown-sensitive jobs, verify DB connectivity
try (Connection c = dataSource.getConnection()) { /* healthy */ } Try / catch
try {
xaFacade.close();
} catch (Exception e) {
// logged as 'unable to close XA connection'; non-fatal at shutdown
LOG.warn("XA close failed, relying on DB-side cleanup/GC", e);
} Prevention
- Set DB idle/network timeouts (wait_timeout, firewall idle) longer than checkpoint interval
- Enable TCP keepalive on JDBC connections
- Monitor DB-side for leaked sessions and clean with session kill if they accumulate
When it happens
Trigger: close() attempts connection.close() on the physical XA connection and the driver throws SQLException — e.g. the network is already broken, the DB killed the session, or the driver already closed it (MySQL SuspendableXAConnection quirks).
Common situations: Job shutdown/recovery while the database connection is stale after long checkpoint intervals; MySQL connections pinned by XA; firewalled/idle connections dropped mid-run.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Connection close failed.
- begin next transaction failed, rollback prepared…
- CLASS_NOT_FOUND
- Close JDBC writer failed.
- COMMON_ILLEGAL_ARGUMENT
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/64f36a4dabd10ce0.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/xa/XaFacadeImplAutoLoad.java:138
@Override
public void close() throws SQLException {
if (connection != null) {
connection.close(); // close connection - likely a wrapper
connection = null;
}
try {
xaConnection.close(); // close likely a pooled AND the underlying connection
} catch (SQLException e) {
// Some databases (e.g. MySQL) rollback changes on normal client disconnect which
// causes an exception if an XA transaction was prepared. Note that resources are
// still released in case of an error. Pinning MySQL connections doesn't help as
// SuspendableXAConnection has the same close() logic.
// Other DBs don't rollback, e.g. for PgSql the previous connection.close() call
// disassociates the connection (and that call works because it has a check for XA)
// and rollback() is not called.
// In either case, not closing the XA connection here leads to the resource leak.
LOG.warn("unable to close XA connection", e);
}
xaResource = null;
}
@Override
public Connection getConnection() {
checkNotNull(connection);
return connection;
}
@Override
public boolean isConnectionValid() throws SQLException {
return isOpen() && connection.isValid(connection.getNetworkTimeout());
}
@Override
public Connection getOrEstablishConnection() throws SQLException {
if (!isOpen()) {View on GitHub (pinned to cf67b549a7)