quarkusio/quarkus · error · IllegalStateException
Not supported for JTA entity managers
Error message
Not supported for JTA entity managers
What it means
TransactionScopedSession is Quarkus's JTA-backed wrapper for Hibernate Session. Because transaction management is delegated to the JTA/ArC transaction layer (via @Transactional or QuarkusTransaction), direct use of the JPA Transaction API is not meaningful, so getTransaction() unconditionally throws IllegalStateException. It signals an API misuse, not a transient failure.
Source
Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java:627
public Object getDelegate() {
try (SessionResult emr = acquireSession()) {
return emr.session.getDelegate();
}
}
@Override
public void close() {
throw new IllegalStateException("Not supported for transaction scoped entity managers");
}
@Override
public boolean isOpen() {
return true;
}
@Override
public Transaction getTransaction() {
throw new IllegalStateException("Not supported for JTA entity managers");
}
@Override
public EntityManagerFactory getEntityManagerFactory() {
return sessionFactory;
}
@Override
public HibernateCriteriaBuilder getCriteriaBuilder() {
checkBlocking();
try (SessionResult emr = acquireSession()) {
return emr.session.getCriteriaBuilder();
}
}
@Override
public Metamodel getMetamodel() {
try (SessionResult emr = acquireSession()) {View on GitHub (pinned to e1c734241f)
Solutions
- Remove the getTransaction()/begin/commit/rollback calls and annotate the method (or class) with @Transactional so Quarkus manages the transaction
- Use io.quarkus.narayana.jta.QuarkusTransaction.begin()/commit()/rollback() or QuarkusTransaction.requiring()/calling() for programmatic transaction control
- If you truly need resource-local behavior, configure a persistence unit with transaction-type RESOURCE_LOCAL outside the JTA-managed session (rare; not the default Quarkus path)
Example fix
// before
void save(User u) {
Transaction tx = session.getTransaction();
tx.begin();
session.persist(u);
tx.commit();
}
// after
@Transactional
void save(User u) {
session.persist(u);
} Defensive patterns
Strategy: validation
Validate before calling
if (session instanceof TransactionScopedSession || session.isDefaultReadOnly()) { /* Quarkus JTA-managed session */ }
// Simplest pre-check: never call getTransaction(); verify the bean was obtained via @Inject in Quarkus
import io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession;
boolean jtaManaged = session instanceof TransactionScopedSession;
if (jtaManaged) { /* use @Transactional or QuarkusTransaction instead */ } Type guard
static boolean isJtaManagedSession(jakarta.persistence.EntityManager em) {
return !(em instanceof org.hibernate.Session s)
|| em.unwrap(org.hibernate.Session.class) != null; // in Quarkus, assume JTA-managed
}
// practical guard:
static boolean supportsLocalTransactions(jakarta.persistence.EntityManager em) {
try { em.getTransaction(); return true; }
catch (IllegalStateException | jakarta.persistence.PersistenceException e) { return false; }
} Try / catch
try {
Transaction tx = session.getTransaction();
tx.begin();
} catch (IllegalStateException e) {
// JTA-managed in Quarkus: switch to @Transactional or QuarkusTransaction.begin()
throw new IllegalStateException("Use @Transactional instead of manual transactions", e);
} Prevention
- Never call getTransaction()/begin()/commit() on injected Session/EntityManager in Quarkus
- Use @Transactional (annotation) or QuarkusTransaction (programmatic) for all transaction control
- When porting resource-local JPA code, audit every em.getTransaction() call site
- Keep transaction logic in service beans, not entities or utilities that get the raw session
When it happens
Trigger: Calling session.getTransaction() (or em.getTransaction()) on a Session/EntityManager obtained from the 'TransactionScopedSession' CDI bean — i.e. any @Inject Session/EntityManager in Quarkus when JTA is the transaction type.
Common situations: Porting code written for resource-local JPA (e.g. Spring Data or plain Java SE Hibernate where em.getTransaction().begin() is normal) to Quarkus; helper/util classes that begin/commit transactions manually; tests copied from non-Quarkus Hibernate examples.
Related errors
- Cannot use the StatelessSession because no transaction is ac
- Could not access JTA Transaction to register synchronization
- Cannot use the StatelessSession because neither a transactio
- Not supported for JTA entity managers
- A generic type is not allowed here; try creating a subclass
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/b10a459705c1996d.
Report an issue: GitHub.