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
- Issue COMMIT or ROLLBACK before sending another BEGIN, or let the driver/ORM own transaction boundaries exclusively
- Disable eager/auto BEGIN in the client pool or ORM (e.g. do not wrap every statement in an explicit transaction)
- 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
- Let exactly one layer (driver autocommit, ORM, or manual BEGIN) own transaction start
- On PostgreSQL dialect, always pair BEGIN/COMMIT and never re-BEGIN inside an open transaction
- In retry logic, track transaction state instead of blindly replaying BEGIN
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
- 0
- Can not locate agent jar file by URL `%s`.
- Can not find field name `%s` in class %s.
- Missing required format info in createBatch()
- Invalid batch handle: statement handle %d
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/dd4479768fe46510.
Report an issue: GitHub.