{"record":{"id":"bd4f9c44d3c5d05b","repo":"hibernate/hibernate-orm","slug":"unable-to-rollback-against-jdbc-connection","errorCode":null,"errorMessage":"Unable to rollback against JDBC Connection","messagePattern":"Unable to rollback against JDBC Connection","errorType":"exception","errorClass":"TransactionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java","lineNumber":147,"sourceCode":"\t}\n\n\t@Override\n\tpublic void rollback() {\n\t\ttry {\n\t\t\tCONNECTION_LOGGER.preparingToRollbackViaConnectionRollback();\n\t\t\tstatus = TransactionStatus.ROLLING_BACK;\n\t\t\tif ( isPhysicallyConnected() ) {\n\t\t\t\tgetConnectionForTransactionManagement().rollback();\n\t\t\t}\n\t\t\telse {\n\t\t\t\terrorIfClosed();\n\t\t\t}\n\t\t\tstatus = TransactionStatus.ROLLED_BACK;\n\t\t\tCONNECTION_LOGGER.transactionRolledBackViaConnectionRollback();\n\t\t}\n\t\tcatch ( SQLException e ) {\n\t\t\tstatus = TransactionStatus.FAILED_ROLLBACK;\n\t\t\tthrow new TransactionException( \"Unable to rollback against JDBC Connection\", e );\n\t\t}\n\n\t\tafterCompletion();\n\t}\n\n\tprotected static boolean determineInitialAutoCommitMode(Connection providedConnection) {\n\t\ttry {\n\t\t\treturn providedConnection.getAutoCommit();\n\t\t}\n\t\tcatch (SQLException e) {\n\t\t\tCONNECTION_LOGGER.unableToAscertainInitialAutoCommit();\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic TransactionStatus getStatus() {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java#L129-L165","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ntry { em.getTransaction().commit(); }\ncatch (Exception e) { em.getTransaction().rollback(); } // rollback itself throws\n\n// after\ntry { em.getTransaction().commit(); }\ncatch (Exception e) {\n  try { em.getTransaction().rollback(); }\n  catch (Exception rb) { log.error(\"rollback failed; discarding session\", rb); }\n  finally { em.close(); } // make sure the broken connection is discarded, not pooled\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  tx.rollback();\n} catch (org.hibernate.TransactionException rb) {\n  // connection + server-side transaction state is unknown: close the session so the\n  // pool discards the connection, then check the DB for orphaned transactions/locks\n  log.error(\"rollback failed; discarding session\", rb);\n} finally {\n  em.close();\n}","preventionTips":["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"],"tags":["hibernate","jdbc","transaction","rollback","connection-pool"],"backgroundTag":"jdbc-rollback-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}