{"record":{"id":"e6e67d671816e9aa","repo":"apache/seatunnel","slug":"failed-to-close-pulsar-client-after-aborting-trans","errorCode":null,"errorMessage":"Failed to close Pulsar client after aborting transactions.","messagePattern":"Failed to close Pulsar client after aborting transactions\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-pulsar/src/main/java/org/apache/seatunnel/connectors/seatunnel/pulsar/sink/PulsarSinkCommitter.java","lineNumber":73,"sourceCode":"        }\n        return commitInfos;\n    }\n\n    @Override\n    public void abort(List<PulsarCommitInfo> commitInfos) throws IOException {\n        if (commitInfos.isEmpty()) {\n            return;\n        }\n        TransactionCoordinatorClient client = transactionCoordinatorClient();\n        for (PulsarCommitInfo commitInfo : commitInfos) {\n            TxnID txnID = commitInfo.getTxnID();\n            client.abort(txnID);\n        }\n        if (this.pulsarClient != null) {\n            try {\n                PulsarConfigUtil.runWithConnectorClassLoader(pulsarClient::close);\n            } catch (Exception e) {\n                throw new IOException(\n                        \"Failed to close Pulsar client after aborting transactions.\", e);\n            }\n        }\n    }\n\n    private TransactionCoordinatorClient transactionCoordinatorClient()\n            throws PulsarClientException {\n        if (coordinatorClient == null) {\n            this.pulsarClient =\n                    PulsarConfigUtil.createClient(clientConfig, PulsarSemantics.EXACTLY_ONCE);\n            this.coordinatorClient = PulsarConfigUtil.getTcClient(pulsarClient);\n        }\n        return coordinatorClient;\n    }\n}\n","sourceCodeStart":55,"sourceCodeEnd":89,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-pulsar/src/main/java/org/apache/seatunnel/connectors/seatunnel/pulsar/sink/PulsarSinkCommitter.java#L55-L89","documentation":"PulsarSinkCommitter.abort aborts active transactions and then closes the Pulsar client; if client.close() throws, it is wrapped in this IOException so the caller sees that the client failed to close after transaction abort. The transactions themselves were already aborted; this is a cleanup failure.","triggerScenarios":"abort(txn) is called, all transactions abort successfully, then pulsarClient.close() (run under the connector classloader) throws an Exception.","commonSituations":"Broker unreachable during close; classloader/shade issues with the Pulsar client; connection already torn down by the engine.","solutions":["Inspect the wrapped cause (e) for the real client close failure (broker connectivity, timeouts)","Verify broker availability and network from the worker running the committer","Ensure the client is not closed twice in custom code paths; retry the job if the abort itself succeeded"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  committer.abort(txn);\n} catch (IOException e) {\n  // abort() succeeded for transactions but client close failed; inspect e.getCause()\n  LOG.warn(\"Client close failed after txn abort: {}\", e.getCause(), e);\n}","preventionTips":["Ensure broker connectivity from worker nodes so close() handshakes succeed","Watch the wrapped cause exception for the root failure","Avoid double-closing the Pulsar client in custom lifecycle code"],"tags":["pulsar","sink","transactions","resource-cleanup","io"],"backgroundTag":"resource-cleanup-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"}