hibernate/hibernate-orm · error · ResourceClosedException
Logical connection is closed
Error message
Logical connection is closed
What it means
ResourceClosedException from LogicalConnectionManagedImpl.manualDisconnect(): session.disconnect() was invoked after the logical connection was already closed. It is a lifecycle usage error — you cannot disconnect an already-closed session; the disconnect operation itself is what failed, no JDBC work was attempted.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/LogicalConnectionManagedImpl.java:181
}
@Override
public void afterTransaction() {
super.afterTransaction();
if ( resolvedConnectionReleaseMode() != ON_CLOSE ) {
// NOTE: we check for !ON_CLOSE here (rather than AFTER_TRANSACTION) to also catch:
// - AFTER_STATEMENT cases that were circumvented due to held resources
// - BEFORE_TRANSACTION_COMPLETION cases that were circumvented because a rollback occurred
// (we don't get a beforeTransactionCompletion event on rollback).
CONNECTION_LOGGER.initiatingConnectionReleaseAfterTransaction( hashCode() );
releaseConnectionIfNeeded();
}
}
@Override
public Connection manualDisconnect() {
if ( closed ) {
throw new ResourceClosedException( "Logical connection is closed" );
}
final var connection = physicalConnection;
releaseConnectionIfNeeded();
return connection;
}
@Override
public void manualReconnect(@Nonnull Connection suppliedConnection) {
if ( closed ) {
throw new ResourceClosedException( "Logical connection is closed" );
}
throw new IllegalStateException( "Cannot manually reconnect unless Connection was originally supplied by user" );
}
private Connection acquire() {
final var eventHandler = getJdbcSessionContext().getEventHandler();
eventHandler.jdbcConnectionAcquisitionStart();
try {View on GitHub (pinned to fad1729dce)
Solutions
- Guard the call: if (session.isOpen()) session.disconnect();
- Drop manual disconnect/reconnect entirely and let hibernate.connection.handling_mode manage acquisition/release
- Ensure close() happens exactly once, in the single place that owns the session lifecycle
Example fix
// before
finally { session.disconnect(); } // throws ResourceClosedException if already closed
// after
finally {
if (session.isOpen()) session.disconnect();
if (session.isOpen()) session.close();
} Defensive patterns
Strategy: validation
Validate before calling
if (session.isOpen()) {
session.disconnect();
} Type guard
static boolean isUsable(org.hibernate.Session s) {
return s != null && s.isOpen();
} Try / catch
catch (org.hibernate.ResourceClosedException e) {
// in cleanup paths this is harmless: the session is already closed; log at debug and continue
} Prevention
- Own the session lifecycle in one place — a single component closes it
- Check isOpen() before any lifecycle operation in finally blocks
- Prefer container/Spring-managed sessions over manual disconnect/reconnect patterns
When it happens
Trigger: session.disconnect() after session.close(); unconditional disconnect() in a finally block that also (or earlier elsewhere) closed the session; double disconnect in layered cleanup code.
Common situations: Old long-conversation disconnect/reconnect recipes (Hibernate 2/3 era) combined with container- or Spring-managed session closing; finally blocks calling disconnect() regardless of prior failure paths that already closed the session.
Related errors
- Session/EntityManager is closed
- EntityManager was already closed
- {} is closed
- The ClassLoaderService cannot be reused (this instance was s
- No child ServiceRegistry registrations found
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/ccbffeb7736440c9.
Report an issue: GitHub.