apache/seatunnel · warning

formatErrorMessage(action, xid, errorCode, errorMessage)

Error message

formatErrorMessage(action, xid, errorCode, errorMessage)

What it means

A WARN log produced by formatErrorMessage(...) in XaFacadeImplAutoLoad.failAndRollback(). When ending a transaction in fail mode (end+rollback for a prepared-but-uncommitted XA transaction) fails with an XAException whose code is below XA_RBBASE (i.e. not a rollback-related code), the facade logs a formatted message with the action, xid and error code instead of retrying rollback. The transaction's fate depends on the recovery mechanism.

Source

Thrown at seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/internal/xa/XaFacadeImplAutoLoad.java:212

                    formatErrorMessage("prepare", of(xid), empty(), "response: " + prepResult));
        }
    }

    @Override
    public void failAndRollback(Xid xid) {
        execute(
                Command.fromRunnable(
                        "end (fail)",
                        xid,
                        () -> {
                            xaResource.end(xid, XAResource.TMFAIL);
                            xaResource.rollback(xid);
                        },
                        err -> {
                            if (err.errorCode >= XA_RBBASE) {
                                rollback(xid);
                            } else {
                                LOG.warn(
                                        formatErrorMessage(
                                                "end (fail)", of(xid), of(err.errorCode)));
                            }
                        }));
    }

    @Override
    public void commit(Xid xid, boolean ignoreUnknown) {
        execute(
                Command.fromRunnableRecoverByWarn(
                        "commit",
                        xid,
                        () ->
                                xaResource.commit(
                                        xid,
                                        false /* not onePhase because the transaction should be prepared already */),
                        e -> buildCommitErrorDesc(e, ignoreUnknown)));
    }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Inspect the errorCode in the log to map to the driver/vendor XA error documentation
  2. Check for duplicate recovery processes rolling back the same xid concurrently
  3. Verify the DB's XA support and driver compatibility; retry the job or run XA recovery (xa_recover) manually if in-doubt transactions accumulate
Defensive patterns

Strategy: retry

Validate before calling

// Ensure no concurrent recovery processes operate on the same xid namespace
// and the DB user has XA privileges:
// GRANT XA_RECOVER_ADMIN ON *.* TO 'user'@'host'; -- MySQL

Try / catch

// XAException handling in user code if replicating abort logic:
try {
    xaResource.end(xid, XAResource.TMFAIL);
    xaResource.rollback(xid);
} catch (XAException e) {
    if (e.errorCode >= XAException.XA_RBBASE) {
        xaResource.rollback(xid);
    } else {
        LOG.warn("end(fail) failed, errorCode=" + e.errorCode + ", xid=" + xid);
    }
}

Prevention

When it happens

Trigger: failAndRollback(xid) executes end(fail)+rollback asynchronously; the XAException error code is unexpected (< XA_RBBASE), so rollback is skipped and only a formatted warning (action, xid, errorCode) is emitted.

Common situations: Transaction already committed/rolled back elsewhere (recovery race); XA protocol violation from the driver; resource manager temporarily unavailable during abort path.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/6a8b251f15a66fbd. Report an issue: GitHub.