hibernate/hibernate-orm · error · SessionException
Cannot redefine the read-only mode on a child session if the
Error message
Cannot redefine the read-only mode on a child session if the connection is reused
What it means
Same guard as the tenant check in SharedSessionBuilderImpl.open(): when a child session shares the parent's transaction coordinator (and physical connection) under multi-tenancy, Hibernate also refuses to change the read-only mode. Calling readOnly(...) on the shared-session builder sets readOnlyChanged, and open() throws because the shared connection/transaction is already in the parent's read-only mode.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/creation/internal/SharedSessionBuilderImpl.java:72
@Override
@Nonnull
public SharedSessionBuilderImplementor withOption(EntityManager.CreationOption option) {
options.apply( option );
return this;
}
@Override
@Nonnull
public SessionImplementor open() {
CORE_LOGGER.openingSession( options.getTenantIdentifierValue() );
if ( original.getFactory().getSessionFactoryOptions().isMultiTenancyEnabled() ) {
if ( options.isTransactionCoordinatorShared() ) {
if ( tenantIdChanged ) {
throw new SessionException(
"Cannot redefine the tenant identifier on a child session if the connection is reused" );
}
if ( readOnlyChanged ) {
throw new SessionException(
"Cannot redefine the read-only mode on a child session if the connection is reused" );
}
}
}
return createSession( options );
}
@Override
@Nonnull
public SessionImplementor openSession() {
return open();
}
@Override
@Nonnull
public SharedSessionBuilderImplementor tenantIdentifier(Object tenantIdentifier) {
super.tenantIdentifier( tenantIdentifier );
tenantIdChanged = true;View on GitHub (pinned to fad1729dce)
Solutions
- Remove the .readOnly(...) call from the shared-session builder and keep the parent's mode.
- Set the read-only mode you need on the parent session before deriving the child.
- Open an independent session (factory.openSession()) instead of sharing when read/write semantics must differ.
- Use session.setDefaultReadOnly()/setReadOnly(entity, ...) on the original session rather than redefining it on a shared child.
Example fix
// before - child shares connection but flips read-only -> SessionException
Session child = parent.sessionWithOptions()
.connection()
.readOnly(true) // different from parent's mode
.openSession();
// after - apply the mode on the parent, then share
parent.setDefaultReadOnly(true);
Session child = parent.sessionWithOptions().connection().openSession(); Defensive patterns
Strategy: validation
Validate before calling
// Only derive a shared child session when the read-only mode will not change boolean sameReadOnly = parentSession.isDefaultReadOnly(); SessionBuilder<?> b = parentSession.sessionWithOptions().connection(); // do NOT call b.readOnly(...) with a different value; keep parent's mode return b.openSession();
Try / catch
catch (SessionException e) {
if (e.getMessage() != null && e.getMessage().contains("read-only mode on a child session")) {
return factory.openSession(); // independent session, its own mode allowed
}
throw e;
} Prevention
- Set read-only on the parent session before spawning shared children.
- Never toggle readOnly() on a builder that shares the transaction coordinator.
- Use session.setDefaultReadOnly() on the original session for read-only optimization.
When it happens
Trigger: session.sessionWithOptions()...openSession() with transaction/connection sharing and multi-tenancy enabled, where .readOnly(true) or .readOnly(false) is called with a value different from the original session's read-only setting.
Common situations: Read-only report sessions derived from a read-write request session; utility code that 'optimizes' child sessions with .readOnly(true); refactoring code so that a shared builder now toggles read-only.
Related errors
- Cannot redefine the tenant identifier on a child session if
- Cannot redefine the tenant identifier on a child session if
- SessionFactory configured for multi-tenancy, but no tenant i
- Session is in read-only mode
- MySQL does not support dropping creating/dropping schemas in
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/83411b30da1b74a2.
Report an issue: GitHub.