hibernate/hibernate-orm · error · HibernateException

Calling method '{methodName}' is not valid without an active

Error message

Calling method '{methodName}' is not valid without an active transaction (Current status: {status})

What it means

ThreadLocalSessionContext hands out a transaction-protection proxy: when no transaction is active on the session, only a whitelist of methods may proceed (beginTransaction, getTransaction, isTransactionInProgress, setFlushMode, setHibernateFlushMode, getFactory, getSessionFactory, getJdbcCoordinator, getTenantIdentifier). Any other invocation — persist, find, createQuery, close — throws this HibernateException naming the method and the current transaction status.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/context/internal/ThreadLocalSessionContext.java:327

					// above has the same basic effect, but we capture that there
					// just to unbind().
					CURRENT_SESSION_LOGGER.allowingInvocationToProceedToClosedSession(methodName);
				}
				else if ( realSession.getTransaction().getStatus() != TransactionStatus.ACTIVE ) {
					// limit the methods available if no transaction is active
					if ( "beginTransaction".equals( methodName )
							|| "getTransaction".equals( methodName )
							|| "isTransactionInProgress".equals( methodName )
							|| "setFlushMode".equals( methodName )
							|| "setHibernateFlushMode".equals( methodName )
							|| "getFactory".equals( methodName )
							|| "getSessionFactory".equals( methodName )
							|| "getJdbcCoordinator".equals( methodName )
							|| "getTenantIdentifier".equals( methodName ) ) {
						CURRENT_SESSION_LOGGER.allowingInvocationToProceedToNonTransactedSession(methodName);
					}
					else {
						throw new HibernateException( "Calling method '" + methodName
								+ "' is not valid without an active transaction (Current status: "
								+ realSession.getTransaction().getStatus() + ")" );
					}
				}
				return method.invoke( realSession, args );
			}
			catch ( InvocationTargetException e ) {
				if (e.getTargetException() instanceof RuntimeException) {
					throw e.getTargetException();
				}
				throw e;
			}
		}

		/**
		 * Setter for property 'wrapped'.
		 *
		 * @param wrapped Value to set for property 'wrapped'.

View on GitHub (pinned to fad1729dce)

Solutions

  1. Begin a transaction first: sessionFactory.getCurrentSession().beginTransaction() is whitelisted and safe to call
  2. For genuinely non-transactional reads use sessionFactory.openSession() in try-with-resources
  3. Set hibernate.current_session_context_class to match the runtime (jta, managed, or the Spring-provided context) instead of thread
  4. Wrap each work unit so begin/commit lives in one place (template/DAO base) instead of relying on callers

Example fix

// before
Session s = sessionFactory.getCurrentSession();
s.persist(user); // throws: no active transaction

// after
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
s.persist(user);
s.getTransaction().commit();
Defensive patterns

Strategy: validation

Validate before calling

Session s = sessionFactory.getCurrentSession();
if (!s.isTransactionInProgress()) { // whitelisted method, safe on the proxy
    s.beginTransaction();
}
s.persist(user);

Try / catch

try {
    session.persist(user);
} catch (org.hibernate.HibernateException e) {
    if (e.getMessage().contains("is not valid without an active transaction")) {
        session.beginTransaction(); // begin is whitelisted; retry once inside the transaction
        session.persist(user);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: hibernate.current_session_context_class=thread and calling e.g. session.persist(user) or session.find(...) on getCurrentSession() before beginTransaction(), or after the previous transaction committed and no new one started.

Common situations: Read-only code paths written without an explicit transaction on the assumption that auto-commit reads work; code migrated from JTA-managed environments where the container guaranteed a transaction; utility/helper classes lazily fetching getCurrentSession(); test harnesses opening sessions without a transaction.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/414f2b375e4db29d. Report an issue: GitHub.