quarkusio/quarkus · error · IllegalStateException
Persistence unit is closed
Error message
Persistence unit is closed
What it means
Thrown by JPAConfig's lazy EntityManagerFactory holder after the persistence unit has been explicitly closed via JPAConfig.stop(). Once closed, the holder refuses to re-bootstrap the EMF, signaling the application is shutting down or the PU was torn down. It guards against recreating EMFs during shutdown (e.g. from a shutdown hook, async task, or scheduled job still running).
Source
Thrown at extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java:175
}
static final class LazyPersistenceUnit {
private final String name;
private final boolean isReactive;
private volatile EntityManagerFactory value;
private volatile boolean closed = false;
LazyPersistenceUnit(String name, boolean isReactive) {
this.name = name;
this.isReactive = isReactive;
}
EntityManagerFactory get() {
if (value == null) {
synchronized (this) {
if (closed) {
throw new IllegalStateException("Persistence unit is closed");
}
if (value == null) {
value = Persistence.createEntityManagerFactory(name,
Collections.singletonMap(IS_REACTIVE_KEY, isReactive));
}
}
}
return value;
}
public synchronized void close() {
closed = true;
EntityManagerFactory emf = this.value;
this.value = null;
if (emf != null) {
emf.close();
}
}View on GitHub (pinned to e1c734241f)
Solutions
- Stop using the persistence unit after shutdown begins; shut down your executors/schedulers before Quarkus terminates.
- Check application state: if this happens at shutdown, treat it as expected and drain tasks gracefully.
- If it happens mid-run, audit for manual calls to JPAConfig.stop()/close in your code or tests.
Example fix
// before executor.submit(() -> emf.createEntityManager()); // may run after shutdown // after executor.shutdown(); executor.awaitTermination(30, TimeUnit.SECONDS); // drain before PU closes
Defensive patterns
Strategy: try-catch
Validate before calling
// Check quarkus runtime status before submitting background JPA work
if (!Quarkus.isStarted() || Quarkus.isStopping()) {
return; // skip DB work during shutdown
} Try / catch
try {
EntityManager em = emf.createEntityManager();
// ...
} catch (IllegalStateException e) {
if ("Persistence unit is closed".equals(e.getMessage())) {
log.info("Skipping task: application is shutting down");
} else { throw e; }
} Prevention
- Drain executors and schedulers before shutdown (graceful lifecycle) using @Lifespan or runWhenShutdown handlers
- Avoid firing new DB tasks from shutdown hooks
- Make scheduled jobs check shutdown state before touching JPA
When it happens
Trigger: Code calls getEntityManagerFactory()/createEntityManager after the application has begun shutdown (JPAConfig.stop invoked); a background thread, timer, or Dev UI request races application termination; closing and then re-accessing the PU in a test.
Common situations: Quartz/Scheduled jobs firing during graceful shutdown; long-running streams writing to the DB while Quarkus stops; tests that stop JPAConfig mid-test then keep using entities.
Related errors
- Not supported for transaction scoped entity managers
- The application is stopping
- The application has not been started
- This PersistenceProvider does not support createEntityManage
- Unable to find an EntityManagerFactory for persistence unit
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/d31c8ea00bf09374.
Report an issue: GitHub.