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

  1. Roll back the transaction explicitly (COMMIT/ROLLBACK or SessionTransactionManager.abortTransaction) and start a new transaction before issuing further commands.
  2. Discard/rebuild the client session; do not reuse a session whose transaction failed.
  3. 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.
  4. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/f9111d25e9d04299. Report an issue: GitHub.