hibernate/hibernate-orm · error · HibernateException
cannot recreate collection while filter is enabled: " + coll
Error message
cannot recreate collection while filter is enabled: " + collectionInfoString( persister, collection, key, session )
What it means
During flush, CollectionUpdateAction (CollectionUpdateAction.java:112) handles updates of owned collections. When a collection 'needs recreate' (true for bag-style collections such as unindexed Lists, arrays, and maps without a collection id, because Hibernate cannot diff rows and must delete-all + reinsert), and a @Filter is currently enabled that affects the collection, Hibernate throws HibernateException("cannot recreate collection while filter is enabled: ..."). The filter changes which rows are visible, so a delete-all/recreate would either drop filtered-out rows or insert rows the filter should hide - Hibernate refuses rather than corrupt data.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/action/internal/CollectionUpdateAction.java:112
// The collection should still be dirty.
throw new AssertionFailure( "collection is not dirty" );
}
// Do nothing - we only need to notify the cache
}
else {
final var eventMonitor = session.getEventMonitor();
final var event = eventMonitor.beginCollectionUpdateEvent();
boolean success = false;
try {
if ( !affectedByFilters && collection.empty() ) {
if ( !emptySnapshot ) {
persister.remove( key, session );
}
//TODO: else we really shouldn't have sent an update event to JFR
}
else if ( collection.needsRecreate( persister ) ) {
if ( affectedByFilters ) {
throw new HibernateException( "cannot recreate collection while filter is enabled: "
+ collectionInfoString( persister, collection, key, session ) );
}
if ( !emptySnapshot ) {
persister.remove( key, session );
}
persister.recreate( collection, key, session );
}
else {
persister.deleteRows( collection, key, session );
persister.updateRows( collection, key, session );
persister.insertRows( collection, key, session );
}
success = true;
}
finally {
eventMonitor.completeCollectionUpdateEvent( event, key, persister.getRole(), success, session );
}
}View on GitHub (pinned to fad1729dce)
Solutions
- Change the collection mapping so row diffs are possible: add @OrderColumn (indexed list), use a Set, or map with a collection id (@CollectionId / idbag) - then needsRecreate() is false and the guard is skipped
- Temporarily disable the filter before mutating the collection: session.disableFilter("name"), flush, then re-enable
- Avoid clearing/replacing filtered bag collections while filters are on; mutate incrementally (add/remove elements) instead of clear()+addAll()
- If the filter logically should not apply to that collection, move the @Filter definition so it does not affect the collection role
Example fix
// before - bag + enabled filter forces recreate and the exception @OneToMany(mappedBy = "order", cascade = ALL) private List<Item> items = new ArrayList<>(); // unindexed bag // after - indexed collection can be diffed row-wise, no recreate needed @OneToMany(mappedBy = "order", cascade = ALL) @OrderColumn(name = "position") private List<Item> items = new ArrayList<>();
Defensive patterns
Strategy: validation
Validate before calling
// before clearing/replacing a collection, make sure no filter affects it
public void replaceItems(Session session, Order order, List<Item> newItems) {
Filter f = session.getEnabledFilter("softDelete");
if (f != null) {
throw new IllegalStateException(
"disable filter 'softDelete' before replacing a bag collection, or map it as indexed/idbag");
}
order.getItems().clear();
order.getItems().addAll(newItems);
} Try / catch
try {
session.flush();
} catch (HibernateException e) {
if (e.getMessage() != null && e.getMessage().startsWith("cannot recreate collection")) {
// disable filters, re-map collection, or reject the operation with a domain error
} else throw e;
} Prevention
- Map filtered entities' collections as indexed (@OrderColumn), Set, or idbag so recreate is never needed
- Wrap filter enable/disable symmetrically around the units of work that need them
- Never clear()+refill bag collections while tenant/soft-delete filters are active
When it happens
Trigger: session.enableFilter(...) active on an entity whose collection is a bag (List without @OrderColumn), primitive array, or map without collection id; then clearing the collection or mutating it in a way that forces needsRecreate()==true; flush/commit triggers CollectionUpdateAction and the guard fires.
Common situations: Soft-delete or tenant filters (@Filter on entities) combined with @OneToMany List fields; multitenancy filters active for the whole request while business code clears/replaces a collection; upgrading mappings from Set to List and suddenly hitting recreate semantics.
Related errors
- cannot recreate collection while filter is enabled [%s : %s]
- null key for collection: %s
- null key for collection: %s
- null key for collection: %s
- queued clear cannot be used with orphan delete
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/74d14443cc3be5cd.
Report an issue: GitHub.