mybatis/mybatis-3 · error · RuntimeSqlException
Could not commit transaction. Cause: {}
Error message
Could not commit transaction. Cause: {} What it means
ScriptRunner throws RuntimeSqlException from commitConnection() when Connection.commit() fails while running a SQL script with autoCommit disabled. ScriptRunner commits after each statement (or per its commitInterval), so any failure the driver reports at commit time — deferred constraint violation, lost connection, lock timeout — surfaces here. The original SQLException is chained as the cause.
Source
Thrown at src/main/java/org/apache/ibatis/jdbc/ScriptRunner.java:193
}
private void setAutoCommit() {
try {
if (autoCommit != connection.getAutoCommit()) {
connection.setAutoCommit(autoCommit);
}
} catch (Throwable t) {
throw new RuntimeSqlException("Could not set AutoCommit to " + autoCommit + ". Cause: " + t, t);
}
}
private void commitConnection() {
try {
if (!connection.getAutoCommit()) {
connection.commit();
}
} catch (Throwable t) {
throw new RuntimeSqlException("Could not commit transaction. Cause: " + t, t);
}
}
private void rollbackConnection() {
try {
if (!connection.getAutoCommit()) {
connection.rollback();
}
} catch (Throwable t) {
// ignore
}
}
private void checkForMissingLineTerminator(StringBuilder command) {
if (command != null && command.toString().trim().length() > 0) {
throw new RuntimeSqlException("Line missing end-of-line terminator (" + delimiter + ") => " + command);
}
}View on GitHub (pinned to 008069adb1)
Solutions
- Read the chained cause (getCause()) to find the real database error and fix that statement/constraint.
- If the script should not be committed piecemeal, call setAutoCommit(true) on the connection or scriptRunner.setAutoCommit(true) before runScript.
- Verify the connection is alive and not participating in an outer transaction that is already rollback-only.
- For lock timeouts, re-run when the contending transaction has finished or shorten the contending transaction.
Example fix
// before Connection conn = dataSource.getConnection(); conn.setAutoCommit(false); new ScriptRunner(conn).runScript(reader); // commit may fail // after Connection conn = dataSource.getConnection(); conn.setAutoCommit(true); // each statement autocommits; no manual commit path new ScriptRunner(conn).runScript(reader);
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the connection can commit before running a long script
if (!conn.isValid(5)) {
throw new IllegalStateException("Connection is not valid; cannot run script");
} Try / catch
try {
runner.runScript(reader);
} catch (RuntimeSqlException e) {
Throwable cause = e.getCause(); // real SQLException
log.error("Script commit failed: {}", cause.getMessage());
// connection is unusable for the failed transaction; roll back / replace it
safeRollback(conn);
} Prevention
- Set autoCommit explicitly (true for standalone scripts) before runScript so commit semantics are known.
- Run migration scripts in a tool designed for them (Flyway/Liquibase) rather than ScriptRunner for transactional DDL.
- Always close the reader and connection in finally/try-with-resources so failed scripts do not leak connections.
When it happens
Trigger: Calling scriptRunner.runScript(reader) (or executeScript) on a Connection with autoCommit=false where connection.commit() throws: deadlock/lock-wait timeout, deferred FK or unique constraint violation, connection already closed or broken, or XA transaction in a bad state.
Common situations: Running schema/data migration scripts (e.g. in tests or on startup) against HSQLDB/PostgreSQL/Oracle with manual transactions; DDL that implicitly fails at commit; scripts run inside an outer transaction that was already marked rollback-only.
Related errors
- Line missing end-of-line terminator ({}) => {}
- Cannot commit, transaction is already closed
- Constructor auto-mapping of ''{0}'' failed. The constructor
- Statement returned {} results where exactly one (1) was expe
- Parameter 'transactionFactory' must not be null
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/5280f73a136e9436.
Report an issue: GitHub.