{"record":{"id":"923c8ca7c07a4866","repo":"apache/seatunnel","slug":"common-writer-operation-failed-923c8c","errorCode":"COMMON_WRITER_OPERATION_FAILED","errorMessage":"unable to open JDBC exactly one writer","messagePattern":"unable to open JDBC exactly one writer","errorType":"error_code","errorClass":"JdbcConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/sink/JdbcExactlyOnceSinkWriter.java","lineNumber":139,"sourceCode":"        this.xidGenerator = xidGenerator;\n        this.outputFormat = outputFormat;\n    }\n\n    private void tryOpen() {\n        if (!isOpen) {\n            isOpen = true;\n            try {\n                xidGenerator.open();\n                xaFacade.open();\n                outputFormat.open();\n                if (!recoverStates.isEmpty()) {\n                    Xid excludeXid = recoverStates.get(0).getXid();\n                    // Rollback pending transactions that should not include recoverStates.\n                    xaGroupOps.recoverAndRollback(context, sinkcontext, xidGenerator, excludeXid);\n                }\n                beginTx(System.currentTimeMillis());\n            } catch (Exception e) {\n                throw new JdbcConnectorException(\n                        CommonErrorCodeDeprecated.WRITER_OPERATION_FAILED,\n                        \"unable to open JDBC exactly one writer\",\n                        e);\n            }\n        }\n    }\n\n    @Override\n    public List<JdbcSinkState> snapshotState(long checkpointId) {\n        checkState(prepareXid != null, \"prepare xid must not be null\");\n        return Collections.singletonList(new JdbcSinkState(prepareXid));\n    }\n\n    @Override\n    public void write(SeaTunnelRow element) {\n        if (element.getArity() == 0) {\n            return;\n        }","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-jdbc/src/main/java/org/apache/seatunnel/connectors/seatunnel/jdbc/sink/JdbcExactlyOnceSinkWriter.java#L121-L157","documentation":"JdbcExactlyOnceSinkWriter.tryOpen() wraps every exception raised while restoring XA state, rolling back stale transactions, and beginning the first XA transaction into a single WRITER_OPERATION_FAILED error. It means the exactly-once sink writer could not reach an operational state: the XA datasource was unusable or the initial transaction could not be started. The root cause is always attached as the cause.","triggerScenarios":"JdbcSinkWriter.tryOpen() is called from write() and prepareCommit(); any Exception from xaGroupOps.recoverAndRollback(...) or beginTx(...) (e.g. xaFacade.open/start failure) in the stateful initialization block is caught and rethrown as this error.","commonSituations":"Wrong JDBC URL/credentials so the XA connection fails; database user lacking XA privileges (e.g. MySQL XA_RECOVER_ADMIN, Oracle XA recovery perms); MariaDB/PostgreSQL XA not enabled; network outage to the database at task startup; a broken XidGenerator or corrupted recovered checkpoint state causing recoverAndRollback to fail.","solutions":["Inspect the wrapped cause 'e' in the exception message/log for the real JDBC/XA error and fix that first","Verify the JDBC URL, username, and password in the sink connection config by connecting manually","Grant the DB user XA privileges required for two-phase commit (MySQL 8: GRANT XA_RECOVER_ADMIN; PostgreSQL: configured max_prepared_transactions > 0)","Check network/firewall/DNS connectivity from the SeaTunnel worker nodes to the database","Restart the job after fixing; if it persists, check recovered transaction state with the DB's XA recovery commands (XA RECOVER / pg_prepared_xacts)"],"exampleFix":"// before\nurl = \"jdbc:mysql://db-host:3306/db\"  // user lacks XA privileges\n// after\nurl = \"jdbc:mysql://db-host:3306/db?serverTimezone=UTC\"\n-- GRANT XA_RECOVER_ADMIN ON *.* TO 'seatunnel'@'%';","handlingStrategy":"validation","validationCode":"// before submitting the job\ntry (Connection c = DriverManager.getConnection(url, user, pass)) {\n    if (!c.getMetaData().supportsXaTransactions()) throw new IllegalStateException(\"XA unsupported\");\n}","typeGuard":"boolean canUseXaSink(DatabaseMetaData md) { try { return md.supportsXaTransactions(); } catch (SQLException e) { return false; } }","tryCatchPattern":"try { writer.open(); } catch (JdbcConnectorException e) { log.error(\"exactly-once writer open failed: {}\", e.getCause(), e); throw e; }","preventionTips":["Validate JDBC URL/credentials with a plain connection before running the job","Grant XA privileges (MySQL XA_RECOVER_ADMIN, PostgreSQL max_prepared_transactions>0)","Check DB reachability from all worker nodes","Test recoverAndRollback path by rehearsing a checkpoint/restart in staging"],"tags":["jdbc","xa","exactly-once","sink","initialization"],"backgroundTag":"database-connection-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}