hibernate/hibernate-orm · error · UnsupportedOperationException
Can't write to a read-only object
Error message
Can't write to a read-only object
What it means
EntityReadOnlyAccess.afterUpdate runs in the post-update phase of flush (with current/previous versions) for cached entities. With the read-only strategy it always throws UnsupportedOperationException because read-only regions never accept writes. Seeing it means an entity cached with usage = read-only went through an update during flush.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/cache/spi/support/EntityReadOnlyAccess.java:93
@Nonnull SharedSessionContractImplementor session,
@Nonnull Object key,
@Nonnull Object value,
@Nullable Object currentVersion,
@Nullable Object previousVersion) {
// LOG.debugf( "Illegal attempt to update item cached as read-only [%s]", key );
throw new UnsupportedOperationException( "Can't update read-only object" );
}
@Override
public boolean afterUpdate(
@Nonnull SharedSessionContractImplementor session,
@Nonnull Object key,
@Nonnull Object value,
@Nullable Object currentVersion,
@Nullable Object previousVersion,
@Nullable SoftLock lock) {
// LOG.debugf( "Illegal attempt to update item cached as read-only [%s]", key );
throw new UnsupportedOperationException( "Can't write to a read-only object" );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Change the entity's cache usage to READ_WRITE or NONSTRICT_READ_WRITE
- Make the entity genuinely immutable and remove the update path
- Evict the entity/region before bulk maintenance and reload afterwards
- Audit hibernate.cache.default_cache_concurrency_strategy and per-entity @Cache values for mutable classes
Example fix
// before
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class ReferenceData { ... } // later mutated -> afterUpdate throws
// after
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ReferenceData { ... } Defensive patterns
Strategy: validation
Validate before calling
org.hibernate.annotations.Cache cache =
ReferenceData.class.getAnnotation(org.hibernate.annotations.Cache.class);
if (cache != null && cache.usage() == CacheConcurrencyStrategy.READ_ONLY) {
log.warn("ReferenceData cached read-only: bulk-replace or evict instead of updating");
} Try / catch
try {
session.merge(entity);
} catch (UnsupportedOperationException e) {
if ("Can't write to a read-only object".equals(e.getMessage())) {
sessionFactory.getCache().evictEntityRegion(entity.getClass());
throw new IllegalStateException("Change @Cache usage to READ_WRITE for "
+ entity.getClass().getName(), e);
}
throw e;
} Prevention
- Treat 'afterUpdate on read-only region' as a mapping bug, not a transient failure
- Keep mutable entities out of read-only regions from day one
- Cover update flows with integration tests against the production cache strategy
When it happens
Trigger: Versioned update of an entity mapped @Cache(usage = READ_ONLY) followed by flush; cascades that dirty a read-only cached entity; global default cache strategy read-only applied to mutable entities.
Common situations: Mutable reference data mapped read-only; optimistic-locking updates touching read-only cached entities; default strategy misconfiguration after a cache rollout.
Related errors
- Can't update read-only object
- cannot recreate collection while filter is enabled: " + coll
- Instance of '" + entityName + "' references an unsaved trans
- Action was vetoed: " + entityAction
- Decomposition not supported for %s
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/7c42e1206fd6259d.
Report an issue: GitHub.