hibernate/hibernate-orm · error · TransactionException
Unable to rollback against JDBC Connection
Error message
Unable to rollback against JDBC Connection
What it means
Rollback-time failure: Connection.rollback() threw an SQLException, so Hibernate sets status FAILED_ROLLBACK and rethrows wrapped in this TransactionException. The physical connection and the server-side transaction are now in an unknown state — the rollback may or may not have reached the database. This exception is nearly always secondary: something already went wrong, and now cleanup is failing too.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java:147
}
@Override
public void rollback() {
try {
CONNECTION_LOGGER.preparingToRollbackViaConnectionRollback();
status = TransactionStatus.ROLLING_BACK;
if ( isPhysicallyConnected() ) {
getConnectionForTransactionManagement().rollback();
}
else {
errorIfClosed();
}
status = TransactionStatus.ROLLED_BACK;
CONNECTION_LOGGER.transactionRolledBackViaConnectionRollback();
}
catch ( SQLException e ) {
status = TransactionStatus.FAILED_ROLLBACK;
throw new TransactionException( "Unable to rollback against JDBC Connection", e );
}
afterCompletion();
}
protected static boolean determineInitialAutoCommitMode(Connection providedConnection) {
try {
return providedConnection.getAutoCommit();
}
catch (SQLException e) {
CONNECTION_LOGGER.unableToAscertainInitialAutoCommit();
return true;
}
}
@Override
@Nonnull
public TransactionStatus getStatus() {View on GitHub (pinned to fad1729dce)
Solutions
- Close the Session immediately afterwards and ensure the pool evicts the connection instead of returning it to circulation
- Check the database for leftover transactions/locks (pg_stat_activity, information_schema.INNODB_TRX) and kill them if needed
- Investigate the ORIGINAL error that triggered the rollback — this exception is noise around it
- Bound transaction size and driver socketTimeout so rollbacks can realistically finish
Example fix
// before
try { em.getTransaction().commit(); }
catch (Exception e) { em.getTransaction().rollback(); } // rollback itself throws
// after
try { em.getTransaction().commit(); }
catch (Exception e) {
try { em.getTransaction().rollback(); }
catch (Exception rb) { log.error("rollback failed; discarding session", rb); }
finally { em.close(); } // make sure the broken connection is discarded, not pooled
} Defensive patterns
Strategy: try-catch
Try / catch
try {
tx.rollback();
} catch (org.hibernate.TransactionException rb) {
// connection + server-side transaction state is unknown: close the session so the
// pool discards the connection, then check the DB for orphaned transactions/locks
log.error("rollback failed; discarding session", rb);
} finally {
em.close();
} Prevention
- Always close the session after a failed rollback — never return that connection to use
- Configure the pool to validate/evict connections on return
- Keep transactions small enough to roll back within driver socket timeouts
- Monitor the DB for long-running and orphaned transactions
When it happens
Trigger: tx.rollback() (typically inside error handling after a failed flush or commit) when the connection is already broken: network gone, DB killed the session, the pool already reclaimed the connection, or rolling back a huge transaction exceeds the driver socket timeout.
Common situations: finally-block rollback during a DB outage; giant batch transactions whose rollback takes longer than socketTimeout; connection killed by the DB while the driver was sending ROLLBACK.
Related errors
- JDBC begin transaction failed:
- Unable to query JDBC Connection for current lock-timeout set
- rollback() called on inactive transaction (in JPA compliant
- Cannot roll back transaction in current status [
- Exception pulsing TransactionCoordinator
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/bd4f9c44d3c5d05b.
Report an issue: GitHub.