hibernate/hibernate-orm · error · IllegalStateException
Illegal attempt to specify a SynchronizationType when buildi
Error message
Illegal attempt to specify a SynchronizationType when building an EntityManager from an EntityManagerFactory defined as RESOURCE_LOCAL (as opposed to JTA)
What it means
JPA requires EntityManagerFactory.createEntityManager(SynchronizationType, ...) to throw IllegalStateException when the persistence unit is RESOURCE_LOCAL. Hibernate enforces this in errorIfResourceLocalDueToExplicitSynchronizationType(): a SynchronizationType argument only makes sense when container/JTA transaction synchronization drives the EntityManager. RESOURCE_LOCAL EntityManagers manage their own resource transactions and cannot be handed to the container for synchronization.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java:912
public Session createEntityManager(@Nullable Map<?,?> map) {
validateNotClosed();
return buildEntityManager( SYNCHRONIZED, map );
}
@Override
@Nonnull
public Session createEntityManager(@Nonnull SynchronizationType synchronizationType) {
validateNotClosed();
errorIfResourceLocalDueToExplicitSynchronizationType();
return buildEntityManager( synchronizationType, null );
}
private void errorIfResourceLocalDueToExplicitSynchronizationType() {
// JPA requires that we throw IllegalStateException in cases where:
// 1) the PersistenceUnitTransactionType (TransactionCoordinator) is non-JTA
// 2) an explicit SynchronizationType is specified
if ( !transactionCoordinatorBuilder.isJta() ) {
throw new IllegalStateException(
"Illegal attempt to specify a SynchronizationType when building an EntityManager from an " +
"EntityManagerFactory defined as RESOURCE_LOCAL (as opposed to JTA)"
);
}
}
@Override
@Nonnull
public Session createEntityManager(@Nonnull SynchronizationType synchronizationType, @Nullable Map<?,?> map) {
validateNotClosed();
errorIfResourceLocalDueToExplicitSynchronizationType();
return buildEntityManager( synchronizationType, map );
}
private StatelessSession createEntityAgent() {
validateNotClosed();
return statelessSessionBuilder( false ).openStatelessSession();
}View on GitHub (pinned to fad1729dce)
Solutions
- Drop the SynchronizationType argument for RESOURCE_LOCAL units: call emf.createEntityManager() or createEntityManager(map) instead
- If you truly need container-managed synchronized EMs, switch the persistence unit to JTA (jakarta.persistence.transactionType=JTA plus a JTA provider like Narayana/Atomikos)
- Branch on the transaction type: read jakarta.persistence.transactionType from emf.getProperties() and choose the createEntityManager overload accordingly
- In Spring, prefer injected EntityManager/@PersistenceContext or SharedEntityManagerCreator instead of manual factory calls
Example fix
// before EntityManager em = emf.createEntityManager(SynchronizationType.SYNCHRONIZED); // IllegalStateException: RESOURCE_LOCAL + explicit SynchronizationType // after (RESOURCE_LOCAL unit) EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // ... em.getTransaction().commit(); em.close();
Defensive patterns
Strategy: validation
Validate before calling
boolean isJta = "JTA".equalsIgnoreCase(
String.valueOf(emf.getProperties().get("jakarta.persistence.transactionType")));
EntityManager em = isJta
? emf.createEntityManager(SynchronizationType.SYNCHRONIZED)
: emf.createEntityManager(); Try / catch
try {
return emf.createEntityManager(SynchronizationType.SYNCHRONIZED);
} catch (IllegalStateException e) {
// RESOURCE_LOCAL unit: retry without a SynchronizationType
return emf.createEntityManager();
} Prevention
- Never hardcode a SynchronizationType in shared code — branch on the unit's transaction type
- Keep container-managed patterns (JTA) and application-managed patterns (RESOURCE_LOCAL) in separate code paths
- In Spring, prefer injected EntityManager so the container picks the correct creation mode
When it happens
Trigger: Calling emf.createEntityManager(SynchronizationType.SYNCHRONIZED) or (SynchronizationType.UNSYNCHRONIZED, map) on a persistence unit whose transaction type is RESOURCE_LOCAL (set in persistence.xml or jakarta.persistence.transactionType=RESOURCE_LOCAL). Typical when code written for a JTA server (WildFly) is reused in Spring Boot/Java SE, which defaults to RESOURCE_LOCAL.
Common situations: Porting an EAR from WildFly to Spring Boot where the same createEntityManager(SynchronizationType) call remains; scaffolding code generated for JTA environments used with a local HikariCP+RESOURCE_LOCAL setup; libraries that always pass SynchronizationType.SYNCHRONIZED for Jakarta EE compatibility.
Related errors
- Unable to register cleanup Synchronization with TransactionM
- Unable to locate current JTA transaction
- Resource-local transaction already active
- Transaction is not accessible when using JTA with JPA-compli
- Transaction was marked for rollback only
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/fe7b2e427f73328d.
Report an issue: GitHub.