prestodb/presto · error · PrestoException
TRANSACTION_ALREADY_ABORTED
TRANSACTION_ALREADY_ABORTED
Error message
Current transaction is aborted, commands ignored until end of transaction block
What it means
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.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java:452
Long idleStartTime = this.idleStartTime.get();
return idleStartTime != null && Duration.nanosSince(idleStartTime).compareTo(idleTimeout) > 0;
}
public void enableRollback(boolean enableRollback)
{
this.enableRollback = enableRollback;
}
public void checkOpenTransaction()
{
Boolean completedStatus = this.completedSuccessfully.get();
if (completedStatus != null) {
if (completedStatus) {
// Should not happen normally
throw new IllegalStateException("Current transaction already committed");
}
else {
throw new PrestoException(TRANSACTION_ALREADY_ABORTED, "Current transaction is aborted, commands ignored until end of transaction block");
}
}
}
private synchronized Map<String, ConnectorId> getCatalogNames()
{
// todo if repeatable read, this must be recorded
Map<String, ConnectorId> catalogNames = new HashMap<>();
catalogByName.values().stream()
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(catalog -> catalogNames.put(catalog.getCatalogName(), catalog.getConnectorId()));
catalogManager.getCatalogs().stream()
.forEach(catalog -> catalogNames.putIfAbsent(catalog.getCatalogName(), catalog.getConnectorId()));
return ImmutableMap.copyOf(catalogNames);
}View on GitHub (pinned to 55bb57d202)
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.
Example fix
// before: keep querying with stale session
connector.execute(session.getTransactionId().get(), sql);
// after: abort and restart transaction on failure
try {
connector.execute(txId, sql);
} catch (PrestoException e) {
if (e.getErrorCode().getCode() == TransactionManager.TransactionErrorCode.TRANSACTION_ALREADY_ABORTED.toErrorCode().getCode()) {
transactionManager.abortTransaction(txId);
txId = transactionManager.beginTransaction(false);
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Java client check before issuing commands
TransactionInfo info = transactionManager.getTransactionInfo(txId);
if (info.isDone() && !info.getCompletionStatus().orElse(false)) {
// transaction already aborted — start a new one
txId = transactionManager.beginTransaction(false);
} Type guard
boolean isTransactionUsable(TransactionManager tm, TransactionId id) {
return !tm.getTransactionInfo(id).isDone()
|| tm.getTransactionInfo(id).getCompletionStatus().orElse(false);
} Try / catch
try {
transactionManager.getCatalogNames(txId, catalog);
} catch (PrestoException e) {
if (e.getErrorCode().getCode() == TransactionErrorCode.TRANSACTION_ALREADY_ABORTED.toErrorCode().getCode()) {
transactionManager.abortTransaction(txId);
txId = transactionManager.beginTransaction(false);
// retry the operation with the new transaction
} else {
throw e;
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- READ_ONLY_VIOLATION
- MULTI_CATALOG_WRITE_CONFLICT
- AUTOCOMMIT_WRITE_CONFLICT
- INVALID_TABLE_PROPERTY
- ACCUMULO_TABLE_EXISTS
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/f9111d25e9d04299.
Report an issue: GitHub.