{"record":{"id":"c8bcb79bccf4e991","repo":"apache/seatunnel","slug":"transient-xa-recovery-scan-failure-on-attempt","errorCode":null,"errorMessage":"Transient XA recovery-scan failure on attempt {}/{}","messagePattern":"Transient XA recovery-scan failure on attempt (.+?)/(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/sink/JdbcSinkAggregatedCommitter.java","lineNumber":255,"sourceCode":"                    alreadyResolved);\n        }\n    }\n\n    /**\n     * Retries the recovery scan with the same bounded budget as XA commit so transient RM outages\n     * do not fail restore immediately.\n     *\n     * @return canonical values returned by the recovery scan\n     */\n    private Set<XidKey> recoverCheckpointTransactions() {\n        int maxCommitAttempts = jdbcSinkConfig.getJdbcConnectionConfig().getMaxCommitAttempts();\n        XaFacade.TransientXaException lastTransientFailure = null;\n        for (int attempt = 1; attempt <= Math.max(1, maxCommitAttempts); attempt++) {\n            try {\n                return normalizeXids(xaFacade.recover());\n            } catch (XaFacade.TransientXaException e) {\n                lastTransientFailure = e;\n                log.warn(\n                        \"Transient XA recovery-scan failure on attempt {}/{}\",\n                        attempt,\n                        Math.max(1, maxCommitAttempts),\n                        e);\n                if (attempt < Math.max(1, maxCommitAttempts)) {\n                    backoffBeforeRetry(\n                            \"recovery scan\", attempt + 1, Math.max(1, maxCommitAttempts));\n                }\n            }\n        }\n        throw new JdbcConnectorException(\n                CommonErrorCodeDeprecated.WRITER_OPERATION_FAILED,\n                String.format(\n                        \"unable to complete the XA recovery scan within %d attempts\",\n                        Math.max(1, maxCommitAttempts)),\n                lastTransientFailure);\n    }\n","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/sink/JdbcSinkAggregatedCommitter.java#L237-L273","documentation":"recoverCheckpointTransactions calls xaFacade.recover() to list in-doubt XA transactions, retrying up to maxCommitAttempts on TransientXaException with backoff. This WARN records each failed attempt; if all attempts fail the underlying transient exception propagates, failing restoreCommit.","triggerScenarios":"xa_recover fails transiently while restoring: temporary connection loss to the database, lock/timeout on the XA recovery scan, DB restarting, or network blips during failover.","commonSituations":"Recovering a large number of in-doubt transactions that makes xa_recover slow/timeout; DB maintenance window during job restart; transient network partitions.","solutions":["Ensure maxCommitAttempts is high enough for flaky networks","Check DB availability and xa_recover performance/indexes","Increase XA/connection timeouts on the datasource","Retry the job after the transient DB issue clears"],"exampleFix":"// before\nmax_commit_attempts = 1\n// after\nmax_commit_attempts = 10","handlingStrategy":"retry","validationCode":"// preflight: attempt a cheap recovery scan before restore\ntry { xaFacade.recover(); } catch (TransientXaException e) { alertDbConnectivity(); }","typeGuard":null,"tryCatchPattern":"for (int attempt = 1; attempt <= maxAttempts; attempt++) {\n    try { return xaFacade.recover(); }\n    catch (TransientXaException e) {\n        if (attempt == maxAttempts) throw e;\n        backoff(attempt);\n    }\n}","preventionTips":["Set maxCommitAttempts > 1 for flaky networks","Monitor DB availability during failover windows","Size xa_recover capacity (in-doubt txn count) appropriately"],"tags":["xa","recovery","retry","network"],"backgroundTag":"request-timeout","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}