prestodb/presto · error · PrestoException

READ_ONLY_VIOLATION

READ_ONLY_VIOLATION

Error message

Cannot execute write in a read-only transaction

What it means

Thrown by TransactionMetadata.checkConnectorWrite when a connector attempts to record a write (checkConnectorWrite) while the enclosing Presto transaction was started read-only. Read-only transactions disallow all data/schema modifications; the write must occur in a read-write transaction.

Source

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

        }

        private ConnectorTransactionHandle beginTransaction(Connector connector)
        {
            if (connector instanceof InternalConnector) {
                return ((InternalConnector) connector).beginTransaction(transactionId, isolationLevel, readOnly);
            }
            else {
                return connector.beginTransaction(isolationLevel, autoCommitContext, readOnly);
            }
        }

        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()) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Start the transaction as read-write: START TRANSACTION READ WRITE (or beginTransaction(false) when creating the transaction programmatically).
  2. Remove the READ ONLY qualifier / fix the client session properties that force read-only transactions.
  3. If the write is accidental, move it outside the transaction or into autocommit mode.
  4. Audit connector code so writes are only attempted when the transaction is known to be writable.

Example fix

// before
START TRANSACTION READ ONLY;
INSERT INTO t VALUES (1);

// after
START TRANSACTION READ WRITE;
INSERT INTO t VALUES (1);
Defensive patterns

Strategy: validation

Validate before calling

-- Before running writes, ensure the transaction is read-write
SHOW TRANSACTION;
-- or in the client: begin a read-write transaction
START TRANSACTION READ WRITE;

Type guard

boolean canWrite(TransactionManager tm, TransactionId id) {
    return !tm.getTransactionInfo(id).isReadOnly();
}

Try / catch

try {
    connectorHandle.beginQuery(txH, metadata);
} catch (PrestoException e) {
    if (e.getErrorCode().getCode() == StandardErrorCode.READ_ONLY_VIOLATION.toErrorCode().getCode()) {
        transactionManager.abortTransaction(txId);
        txId = transactionManager.beginTransaction(false); // read-write
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: A connector calls checkConnectorWrite(connectorId) during a transaction created with readOnly=true (e.g. START TRANSACTION READ ONLY, or a session defaulting to read-only), and the connector attempts an INSERT/UPDATE/DDL through that transaction.

Common situations: Session was opened READ ONLY but the client later runs a write statement; JDBC/CLI default transaction mode is read-only while an application assumes read-write; a metadata plugin records a write during a read-only transaction.

Related errors


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