{"record":{"id":"f9111d25e9d04299","repo":"prestodb/presto","slug":"transaction-already-aborted","errorCode":"TRANSACTION_ALREADY_ABORTED","errorMessage":"Current transaction is aborted, commands ignored until end of transaction block","messagePattern":"Current transaction is aborted, commands ignored until end of transaction block","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java","lineNumber":452,"sourceCode":"            Long idleStartTime = this.idleStartTime.get();\n            return idleStartTime != null && Duration.nanosSince(idleStartTime).compareTo(idleTimeout) > 0;\n        }\n\n        public void enableRollback(boolean enableRollback)\n        {\n            this.enableRollback = enableRollback;\n        }\n\n        public void checkOpenTransaction()\n        {\n            Boolean completedStatus = this.completedSuccessfully.get();\n            if (completedStatus != null) {\n                if (completedStatus) {\n                    // Should not happen normally\n                    throw new IllegalStateException(\"Current transaction already committed\");\n                }\n                else {\n                    throw new PrestoException(TRANSACTION_ALREADY_ABORTED, \"Current transaction is aborted, commands ignored until end of transaction block\");\n                }\n            }\n        }\n\n        private synchronized Map<String, ConnectorId> getCatalogNames()\n        {\n            // todo if repeatable read, this must be recorded\n            Map<String, ConnectorId> catalogNames = new HashMap<>();\n            catalogByName.values().stream()\n                    .filter(Optional::isPresent)\n                    .map(Optional::get)\n                    .forEach(catalog -> catalogNames.put(catalog.getCatalogName(), catalog.getConnectorId()));\n\n            catalogManager.getCatalogs().stream()\n                    .forEach(catalog -> catalogNames.putIfAbsent(catalog.getCatalogName(), catalog.getConnectorId()));\n\n            return ImmutableMap.copyOf(catalogNames);\n        }","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java#L434-L470","documentation":"Thrown by InMemoryTransactionManager's checkOpenTransaction when an operation references a transaction that has already been aborted (completedStatus=false). Once a transaction is aborted, Presto rejects all further commands until the client finishes/acknowledges the end of the transaction block, mirroring PostgreSQL's 'current transaction is aborted' semantics.","triggerScenarios":"Calling any TransactionManager API (getTransactionCatalogMetadata, getFunctionNamespaceTransaction, checkConnectorWrite, etc. via checkAndSetActive) with a transaction id whose TransactionMetadata.completedStatus is Boolean.FALSE, i.e. after an abort/failure was already recorded.","commonSituations":"Client keeps sending queries on the same session after a statement inside an explicit transaction failed and Presto auto-aborted the transaction; retrying a query on a stale session after a rollback; connector failure mid-transaction triggered abort and subsequent catalog/lookups still reference the dead transaction id.","solutions":["Roll back the transaction explicitly (COMMIT/ROLLBACK or SessionTransactionManager.abortTransaction) and start a new transaction before issuing further commands.","Discard/rebuild the client session; do not reuse a session whose transaction failed.","Fix the root-cause error that aborted the transaction (check the earlier exception in the query log) so future transactions do not abort mid-flight.","Add client-side logic to detect TRANSACTION_ALREADY_ABORTED and reset the transaction state automatically."],"exampleFix":"// before: keep querying with stale session\nconnector.execute(session.getTransactionId().get(), sql);\n\n// after: abort and restart transaction on failure\ntry {\n    connector.execute(txId, sql);\n} catch (PrestoException e) {\n    if (e.getErrorCode().getCode() == TransactionManager.TransactionErrorCode.TRANSACTION_ALREADY_ABORTED.toErrorCode().getCode()) {\n        transactionManager.abortTransaction(txId);\n        txId = transactionManager.beginTransaction(false);\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Java client check before issuing commands\nTransactionInfo info = transactionManager.getTransactionInfo(txId);\nif (info.isDone() && !info.getCompletionStatus().orElse(false)) {\n    // transaction already aborted — start a new one\n    txId = transactionManager.beginTransaction(false);\n}","typeGuard":"boolean isTransactionUsable(TransactionManager tm, TransactionId id) {\n    return !tm.getTransactionInfo(id).isDone()\n        || tm.getTransactionInfo(id).getCompletionStatus().orElse(false);\n}","tryCatchPattern":"try {\n    transactionManager.getCatalogNames(txId, catalog);\n} catch (PrestoException e) {\n    if (e.getErrorCode().getCode() == TransactionErrorCode.TRANSACTION_ALREADY_ABORTED.toErrorCode().getCode()) {\n        transactionManager.abortTransaction(txId);\n        txId = transactionManager.beginTransaction(false);\n        // retry the operation with the new transaction\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always roll back or commit after any statement failure inside a transaction before sending more commands.","Treat a failed statement as invalidating the whole transaction (Postgres-like semantics).","Track transaction lifecycle client-side; never cache a transaction id across failure boundaries.","Log and inspect the original aborting error to remove the root cause."],"tags":["transaction","presto","session-state"],"backgroundTag":"transaction-already-aborted","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}