{"record":{"id":"192a6551d662e3db","repo":"hibernate/hibernate-orm","slug":"jdbc-begin-transaction-failed","errorCode":null,"errorMessage":"JDBC begin transaction failed: ","messagePattern":"JDBC begin transaction failed: ","errorType":"exception","errorClass":"TransactionException","httpStatus":null,"severity":"critical","filePath":"hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java","lineNumber":71,"sourceCode":"\t\tgetResourceRegistry().releaseResources();\n\t}\n\n\t// PhysicalJdbcTransaction impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n\tprotected abstract Connection getConnectionForTransactionManagement();\n\n\t@Override\n\tpublic void begin() {\n\t\ttry {\n\t\t\tif ( !doConnectionsFromProviderHaveAutoCommitDisabled() ) {\n\t\t\t\tCONNECTION_LOGGER.preparingToBeginViaSetAutoCommitFalse();\n\t\t\t\tgetConnectionForTransactionManagement().setAutoCommit( false );\n\t\t\t\tCONNECTION_LOGGER.transactionBegunViaSetAutoCommitFalse();\n\t\t\t}\n\t\t\tstatus = TransactionStatus.ACTIVE;\n\t\t}\n\t\tcatch( SQLException e ) {\n\t\t\tthrow new TransactionException( \"JDBC begin transaction failed: \", e );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void commit() {\n\t\tif ( isPhysicallyConnected() ) {\n\t\t\tcommitConnection();\n\t\t}\n\t\telse {\n\t\t\terrorIfClosed();\n\t\t\tstatus = TransactionStatus.COMMITTED;\n\t\t}\n\t\tafterCompletion();\n\t}\n\n\tprivate void commitConnection() {\n\t\ttry {\n\t\t\tCONNECTION_LOGGER.preparingToCommitViaConnectionCommit();","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java#L53-L89","documentation":"Thrown when Hibernate cannot start a physical JDBC transaction: AbstractLogicalConnectionImplementor.begin() calls Connection.setAutoCommit(false) (unless the provider disables autocommit) and wraps any SQLException in this TransactionException. The message itself is generic; the real cause is always chained as getCause(). The transaction never became ACTIVE, so nothing was begun on the database side.","triggerScenarios":"session.beginTransaction() / EntityTransaction.begin() on a resource-local (JDBC) Hibernate session where setAutoCommit(false) throws: the pool handed out an already-closed or network-dead connection, the DB is restarting/failing over, the driver forbids setAutoCommit (e.g. a connection already enlisted in an XA transaction), or the connection was reclaimed mid-flight.","commonSituations":"MySQL wait_timeout recycling connections while the pool maxLifetime is larger; DB restart or failover under load; reusing a Session after an earlier exception left its connection broken; accidentally using Hibernate's JDBC transaction coordinator on a JTA/XA-managed connection.","solutions":["Inspect the chained SQLException (SQLState + vendor error code) to identify the real failure before changing anything","Fix pool settings: set maxLifetime below the DB idle timeout and enable checkout validation (isValid / test query)","If running under JTA, configure hibernate.transaction.coordinator_class=jta so Hibernate does not drive setAutoCommit itself","If transient (connection class 08xxx), retry the whole unit of work on a fresh Session/EntityManager"],"exampleFix":"// before\nem.getTransaction().begin(); // TransactionException: JDBC begin transaction failed\n\n// after\ntry {\n  em.getTransaction().begin();\n} catch (org.hibernate.TransactionException te) {\n  Throwable root = te.getCause();\n  while (root.getCause() != null) root = root.getCause();\n  // root is the SQLException: classify (transient vs fatal) and retry with a new EntityManager if transient\n}\n// plus pool hygiene: hikari maxLifetime < DB wait_timeout, connection validation enabled","handlingStrategy":"try-catch","validationCode":"// validate the pooled connection before beginning, on a session you are about to use\nem.unwrap(org.hibernate.Session.class).doReturningWork(conn -> conn.isValid(1));","typeGuard":"static boolean isJdbcBeginFailure(Throwable t) {\n  return t instanceof org.hibernate.TransactionException\n      && t.getMessage() != null\n      && t.getMessage().startsWith(\"JDBC begin transaction failed\");\n}","tryCatchPattern":"try {\n  tx.begin();\n} catch (org.hibernate.TransactionException e) {\n  Throwable root = e.getCause();\n  while (root != null && root.getCause() != null) root = root.getCause();\n  // root is the SQLException: classify by SQLState (08xxx = connection, transient) and\n  // either retry with a fresh EntityManager or surface the real cause to ops\n}","preventionTips":["Set pool maxLifetime below the database's idle-connection timeout (e.g. HikariCP maxLifetime < MySQL wait_timeout)","Enable connection validation on checkout so dead connections never reach begin()","Never reuse a Session after any exception without closing it first","Run begin() inside try and guarantee rollback or close in finally"],"tags":["hibernate","jdbc","transaction","connection-pool","autocommit"],"backgroundTag":"jdbc-begin-transaction-failed","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}