apache/shardingsphere · error · InTransactionException

There is already a transaction in progress

Error message

There is already a transaction in progress

What it means

InTransactionException ('There is already a transaction in progress') thrown by BeginTransactionProxyBackendHandler.execute when a BEGIN arrives while connectionSession.getTransactionStatus().isInTransaction() is true, the dialect does not support auto-commit in nested transactions, and the dialect has a default schema (schema option exposes getDefaultSchema()). In that combination the proxy refuses to silently nest transactions and surfaces the same error the backing database (e.g. PostgreSQL) would give.

Source

Thrown at proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/tcl/local/type/BeginTransactionProxyBackendHandler.java:58

    
    private final ProxyBackendTransactionManager transactionManager;
    
    private final DialectDatabaseMetaData dialectDatabaseMetaData;
    
    public BeginTransactionProxyBackendHandler(final TCLStatement sqlStatement, final ConnectionSession connectionSession) {
        this.sqlStatement = sqlStatement;
        this.connectionSession = connectionSession;
        transactionManager = new ProxyBackendTransactionManager(connectionSession.getDatabaseConnectionManager());
        dialectDatabaseMetaData = new DatabaseTypeRegistry(connectionSession.getProtocolType()).getDialectDatabaseMetaData();
    }
    
    @Override
    public ResponseHeader execute() throws SQLException {
        if (connectionSession.getTransactionStatus().isInTransaction()) {
            if (dialectDatabaseMetaData.getTransactionOption().isSupportAutoCommitInNestedTransaction()) {
                transactionManager.commit();
            } else if (dialectDatabaseMetaData.getSchemaOption().getDefaultSchema().isPresent()) {
                throw new InTransactionException();
            }
        }
        transactionManager.begin();
        return new UpdateResponseHeader(sqlStatement);
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Issue COMMIT or ROLLBACK before sending another BEGIN, or let the driver/ORM own transaction boundaries exclusively
  2. Disable eager/auto BEGIN in the client pool or ORM (e.g. do not wrap every statement in an explicit transaction)
  3. Guard client code: check the session transaction state (e.g. JDBC Connection.getAutoCommit() / transaction status) before BEGIN

Example fix

-- before
BEGIN;
SELECT 1;
BEGIN;  -- ERROR: There is already a transaction in progress

-- after
BEGIN;
SELECT 1;
COMMIT;
BEGIN;
Defensive patterns

Strategy: validation

Validate before calling

// client-side: check before sending BEGIN over the proxy connection
if (!connection.getAutoCommit()) {
    connection.commit(); // or rollback(): close the open transaction first
}
connection.setAutoCommit(false); // effectively BEGIN

Try / catch

try {
    statement.execute("BEGIN");
} catch (final SQLException ex) {
    if (ex.getMessage() != null && ex.getMessage().contains("There is already a transaction in progress")) {
        statement.execute("COMMIT");
        statement.execute("BEGIN"); // retry once from a clean state
    } else {
        throw ex;
    }
}

Prevention

When it happens

Trigger: Client sends BEGIN twice without COMMIT/ROLLBACK, or sends BEGIN while an implicitly started transaction is open, on a dialect like PostgreSQL where TransactionOption.isSupportAutoCommitInNestedTransaction() is false and a default schema exists. MySQL-style dialects instead commit the outer transaction and begin a new one.

Common situations: ORM/connection pools that auto-BEGIN (autocommit=false plus an eager BEGIN) layered on manual transaction control; retry logic re-issuing BEGIN after a lost response; drivers enabling implicit transactions before SET commands that themselves start transactions; migrating an app from MySQL (nested BEGIN tolerated) to PostgreSQL.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/dd4479768fe46510. Report an issue: GitHub.