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
- Begin a transaction first: sessionFactory.getCurrentSession().beginTransaction() is whitelisted and safe to call
- For genuinely non-transactional reads use sessionFactory.openSession() in try-with-resources
- Set hibernate.current_session_context_class to match the runtime (jta, managed, or the Spring-provided context) instead of thread
- 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
- Wrap all current-session work in begin/commit via one shared template
- Use openSession() for non-transactional reads instead of bypassing the proxy
- Match hibernate.current_session_context_class to the actual runtime environment
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
- Unable to locate current JTA transaction
- Could not obtain TransactionManager from JtaPlatform
- No session currently bound to execution context
- No CurrentSessionContext configured
- The {storageEngine} storage engine is not supported
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/414f2b375e4db29d.
Report an issue: GitHub.