prestodb/presto · error · SemanticException

INVALID_TRANSACTION_MODE

INVALID_TRANSACTION_MODE

Error message

Multiple transaction isolation levels specified

What it means

Validation inside extractIsolationLevel, which scans the characteristics of a START TRANSACTION statement: more than one ISOLATION LEVEL clause was supplied (e.g. 'START TRANSACTION ISOLATION LEVEL READ COMMITTED, ISOLATION LEVEL SERIALIZABLE'), so the isolation level is ambiguous.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/execution/StartTransactionTask.java:79

                isolationLevel.orElse(TransactionManager.DEFAULT_ISOLATION),
                readOnly.orElse(TransactionManager.DEFAULT_READ_ONLY),
                false);

        stateMachine.setStartedTransactionId(transactionId);

        // Since the current session does not contain this new transaction ID, we need to manually mark it as inactive
        // when this statement completes.
        transactionManager.trySetInactive(transactionId);

        return immediateFuture(null);
    }

    private static Optional<IsolationLevel> extractIsolationLevel(StartTransaction startTransaction)
    {
        if (startTransaction.getTransactionModes().stream()
                .filter(Isolation.class::isInstance)
                .count() > 1) {
            throw new SemanticException(INVALID_TRANSACTION_MODE, startTransaction, "Multiple transaction isolation levels specified");
        }

        return startTransaction.getTransactionModes().stream()
                .filter(Isolation.class::isInstance)
                .map(Isolation.class::cast)
                .map(Isolation::getLevel)
                .map(StartTransactionTask::convertLevel)
                .findFirst();
    }

    private static Optional<Boolean> extractReadOnly(StartTransaction startTransaction)
    {
        if (startTransaction.getTransactionModes().stream()
                .filter(TransactionAccessMode.class::isInstance)
                .count() > 1) {
            throw new SemanticException(INVALID_TRANSACTION_MODE, startTransaction, "Multiple transaction read modes specified");
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Keep a single ISOLATION LEVEL clause in START TRANSACTION.
  2. Fix the SQL builder/template so transaction modes are not concatenated twice.
  3. Validate the statement text before execution in generated-SQL pipelines.

Example fix

-- before
START TRANSACTION ISOLATION LEVEL READ COMMITTED, ISOLATION LEVEL SERIALIZABLE;
-- after
START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Defensive patterns

Strategy: validation

Validate before calling

// count isolation clauses before execution
int n = countMatches(sql, "ISOLATION LEVEL"); if (n > 1) reject(sql);

Try / catch

// catch SemanticException with code INVALID_TRANSACTION_MODE and message 'Multiple transaction isolation levels specified'; fix SQL and re-run

Prevention

When it happens

Trigger: START TRANSACTION containing two or more Isolation transaction modes, e.g. START TRANSACTION ISOLATION LEVEL READ COMMITTED, ISOLATION LEVEL SERIALIZABLE — extractIsolationLevel() counts >1 Isolation instances.

Common situations: Duplicated clauses from query generation bugs, templated SQL concatenating transaction-mode fragments, copy-paste mistakes in scripts.

Related errors


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