hibernate/hibernate-orm · error · IllegalStateException
EntityManagerFactory is closed
Error message
EntityManagerFactory is closed
What it means
Most SessionFactory/EntityManagerFactory accessors (getProperties(), metamodel access, createEntityManager()) start with validateNotClosed(), which throws IllegalStateException once the factory's status is CLOSED. Hibernate intentionally fails fast instead of serving stale data from a shut-down factory. The factory is a heavyweight object whose services are released by close().
Source
Thrown at hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java:780
public StatelessSession openStatelessSession(@Nonnull Connection connection) {
return withStatelessOptions().connection( connection ).openStatelessSession();
}
@Override
public void addObserver(@Nonnull SessionFactoryObserver observer) {
observerChain.addObserver( observer );
}
@Override
@Nonnull
public Map<String, Object> getProperties() {
validateNotClosed();
return settings;
}
protected void validateNotClosed() {
if ( status == Status.CLOSED ) {
throw new IllegalStateException( "EntityManagerFactory is closed" );
}
}
@Override
public String getUuid() {
return uuid;
}
@Override
public String getName() {
return name;
}
@Override
public String getJndiName() {
return jndiName;
}
View on GitHub (pinned to fad1729dce)
Solutions
- Guard every access with if (emf != null && emf.isOpen()) before using the factory
- Fix the lifecycle ordering: close the EMF last, after all components that use it (check @PreDestroy / shutdown-hook order, Spring dependsOn)
- Cache any settings you need after close (e.g. copy getProperties() into your own map during startup) instead of reading them later
- In tests, use a shared EMF per suite or recreate it in @BeforeAll/@AfterAll so no test touches a closed factory
Example fix
// before
public Map<String, Object> config() {
return emf.getProperties(); // throws if container already closed the EMF
}
// after
public Map<String, Object> config() {
if (emf == null || !emf.isOpen()) {
throw new IllegalStateException("application context already shut down");
}
return emf.getProperties();
} Defensive patterns
Strategy: validation
Validate before calling
public Map<String, Object> safeProperties(EntityManagerFactory emf) {
if (!emf.isOpen()) {
throw new IllegalStateException("EntityManagerFactory is closed; cannot read properties");
}
return emf.getProperties();
} Try / catch
try {
return emf.getProperties();
} catch (IllegalStateException e) {
// factory closed — fall back to a snapshot captured at startup
return startupPropertySnapshot;
} Prevention
- Copy any settings you need for shutdown/reporting into your own structures during startup
- Give the EMF a single owner and close it last in the shutdown order (Spring: let the container own it)
- Guard all long-lived references with isOpen() before use, especially in background threads and shutdown hooks
When it happens
Trigger: Calling emf.getProperties(), emf.createEntityManager(), or any other guarded method after emf.close() (or Spring container shutdown closing the shared EMF). Typical in @PreDestroy ordering bugs, static EMF holders, or code that caches the EMF across application restarts in the same JVM.
Common situations: Spring Boot devtools restart or context refresh closing the EMF while a background thread still uses it; shutdown hooks that close the factory before other hooks read settings; test classes sharing a container-managed EMF that was closed by a previous test suite; fat-client apps that rebuild the factory but keep old references.
Related errors
- EntityManagerFactory is already closed
- EntityManager was already closed
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/d186f6c2a8bdfb64.
Report an issue: GitHub.