prestodb/presto · error · PrestoException

AUTOCOMMIT_WRITE_CONFLICT

AUTOCOMMIT_WRITE_CONFLICT

Error message

Catalog  only supports writes using autocommit

What it means

Thrown by TransactionMetadata.checkConnectorWrite when the connector's transaction metadata reports isSingleStatementWritesOnly() (a connector that only supports single-statement, autocommit writes) but the write occurs inside a non-autocommit context (an explicit multi-statement transaction).

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/transaction/InMemoryTransactionManager.java:597

        public synchronized void checkConnectorWrite(ConnectorId connectorId)
        {
            checkOpenTransaction();
            ConnectorTransactionMetadata transactionMetadata = connectorIdToMetadata.get(connectorId);
            checkArgument(transactionMetadata != null, "Cannot record write for connector not part of transaction");
            if (readOnly) {
                throw new PrestoException(READ_ONLY_VIOLATION, "Cannot execute write in a read-only transaction");
            }
            if (!writtenConnectorId.compareAndSet(null, connectorId) && !writtenConnectorId.get().equals(connectorId)) {
                throw new PrestoException(
                        MULTI_CATALOG_WRITE_CONFLICT,
                        format(
                                "Multi-catalog writes not supported in a single transaction. Attempt write to catalog %s, but already wrote to catalog %s",
                                connectorId,
                                writtenConnectorId.get()));
            }
            if (transactionMetadata.isSingleStatementWritesOnly() && !autoCommitContext) {
                throw new PrestoException(AUTOCOMMIT_WRITE_CONFLICT, "Catalog " + connectorId + " only supports writes using autocommit");
            }
        }

        public synchronized ListenableFuture<?> asyncCommit()
        {
            if (!completedSuccessfully.compareAndSet(null, true)) {
                if (completedSuccessfully.get()) {
                    // Already done
                    return immediateFuture(null);
                }
                // Transaction already aborted
                return immediateFailedFuture(new PrestoException(TRANSACTION_ALREADY_ABORTED, "Current transaction has already been aborted"));
            }

            ListenableFuture<?> functionNamespaceFuture = Futures.allAsList(functionNamespaceTransactions.values().stream()
                    .map(transactionMetadata -> finishingExecutor.submit(transactionMetadata::commit))
                    .collect(toImmutableList()));

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Run the write in autocommit mode (do not wrap it in START TRANSACTION/COMMIT).
  2. Remove only that connector's writes from the multi-statement transaction and execute them separately.
  3. Switch to a connector that supports transactional writes if transactional semantics are required.
  4. Check the connector's isSingleStatementWritesOnly capability before designing transactional workflows against it.

Example fix

// before
START TRANSACTION;
INSERT INTO limited.t VALUES (1);
COMMIT;

// after: autocommit
INSERT INTO limited.t VALUES (1);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the connector supports transactional writes before using it in a transaction
ConnectorTransactionMetadata meta = transactionMetadata.getConnectorTransactionMetadata(connectorId);
if (meta != null && meta.isSingleStatementWritesOnly()) {
    // run this write in autocommit instead
}

Type guard

boolean supportsTransactionalWrite(ConnectorMetadata metadata) {
    return !metadata.isSingleStatementWritesOnly();
}

Try / catch

try {
    transactionMetadata.checkConnectorWrite(connectorId);
} catch (PrestoException e) {
    if (e.getErrorCode().getCode() == StandardErrorCode.AUTOCOMMIT_WRITE_CONFLICT.toErrorCode().getCode()) {
        // move the statement outside the transaction and re-execute with autocommit
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A write is performed against a catalog whose ConnectorMetadata isSingleStatementWritesOnly returns true while autoCommitContext is false, i.e. inside START TRANSACTION ... COMMIT rather than in autocommit mode.

Common situations: Wrapping writes to connectors like certain JDBC/Kafka-style catalogs (single-statement-write connectors) inside explicit transactions; application always wraps statements in transactions; connector upgraded to declare single-statement-writes-only and existing transactional code starts failing.

Related errors


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