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
- Start the transaction as read-write: START TRANSACTION READ WRITE (or beginTransaction(false) when creating the transaction programmatically).
- Remove the READ ONLY qualifier / fix the client session properties that force read-only transactions.
- If the write is accidental, move it outside the transaction or into autocommit mode.
- 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
- Do not add READ ONLY to transactions that may perform writes.
- Check session/connector defaults that force read-only transaction mode.
- Separate read-only analytical transactions from write workloads.
- Inspect SHOW TRANSACTION or TransactionInfo.isReadOnly before issuing DML/DDL.
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
- TRANSACTION_ALREADY_ABORTED
- 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/6bc0ce4b1493452a.
Report an issue: GitHub.