apache/seatunnel · warning
unable to fail/rollback current transaction, xid=
Error message
unable to fail/rollback current transaction, xid={} What it means
This is a WARN-level log emitted by JdbcExactlyOnceSinkWriter when it tries to roll back the current in-doubt XA transaction via the XA facade (xaResource.fail + rollback) and the XA operation throws. The writer swallows the exception because it is already in an error/cleanup path (abort or close); the transaction stays heuristically in-doubt in the database and currentXid is cleared regardless.
Solutions
- Inspect the WARN's cause stack trace to identify the XA error code and fix the root connection/DB issue
- Check DB-side in-doubt transactions (e.g. RECOVER PREPARED in Postgres, XA RECOVER in MySQL) and roll them back manually
- Verify network stability and DB timeout settings (wait_timeout, transaction timeout) larger than checkpoint interval
- Retry the failing job; Zeta recovery plus database-side cleanup restores exactly-once state
Example fix
// before: silent warn leaves DB transaction in doubt
} catch (Exception e) {
LOG.warn("unable to fail/rollback current transaction, xid={}", xid, e);
}
// after: record xid in state so recovery tooling can clean it up
} catch (Exception e) {
LOG.warn("unable to fail/rollback current transaction, xid={}", xid, e);
pendingRollbackXids.add(xid); // expose for monitoring/manual XA RECOVER
} Defensive patterns
Strategy: try-catch
Try / catch
try {
xaFacade.failAndRollback(xid);
} catch (Exception e) {
LOG.warn("XA rollback failed, inspect DB in-doubt txns for xid={}", xid, e);
alertOpsForManualRecovery(xid); // XA RECOVER / RECOVER PREPARED
} Prevention
- Set DB connection and transaction timeouts longer than the job's checkpoint interval
- Monitor cluster/job failures so rollbacks happen while the DB connection is still healthy
- Periodically scan for in-doubt XA transactions (XA RECOVER) and clean them
- Keep network between workers and database reliable (health checks, retries)
When it happens
Trigger: abortPrepare or close calls failAndRollbackCurrentXidQuietly while the XA resource is disconnected, the XID is already completed/unknown on the DB side, or the DB rejects the fail/rollback command (XAER_RMFAIL, XAER_NOTA, connection lost).
Common situations: Job fails mid-transaction and the DB connection is already dead; database restarted between prepare and rollback; driver-level XA errors like 'XAER_RMFAIL: connection closed'; MySQL/Postgres cleaned up the transaction after timeout.
Related errors
- JDBC XA sink requires max_retries equal to 0 when…
- XA_OPERATION_FAILED
- COMMON_WRITER_OPERATION_FAILED
- COMMON_WRITER_OPERATION_FAILED
- Couldn't obtain database name
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/230612845aa9ca45.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/sink/JdbcExactlyOnceSinkWriter.java:321
} catch (Exception recoveryException) {
LOG.warn(
"recovery after rollback prepared transaction failure also failed, xid={}",
failedRollbackXid,
recoveryException);
rollbackFailure.addSuppressed(recoveryException);
}
}
private void failAndRollbackCurrentXidQuietly() {
if (currentXid == null || !xaFacade.isOpen()) {
return;
}
Xid xid = currentXid;
try {
LOG.debug("remove current transaction, xid={}", xid);
xaFacade.failAndRollback(xid);
} catch (Exception e) {
LOG.warn("unable to fail/rollback current transaction, xid={}", xid, e);
} finally {
currentXid = null;
}
}
private void prepareCurrentTx() throws IOException {
checkState(currentXid != null, "no current xid");
outputFormat.flush();
Exception endAndPrepareException = null;
try {
xaFacade.endAndPrepare(currentXid);
} catch (Exception e) {
endAndPrepareException = e;
throw new JdbcConnectorException(
JdbcConnectorErrorCode.XA_OPERATION_FAILED,
"unable to prepare current xa transaction",
e);View on GitHub (pinned to cf67b549a7)