hibernate/hibernate-orm · error · IllegalStateException
Cannot overwrite existing state, should clear previous…
Error message
Cannot overwrite existing state, should clear previous state first
What it means
EffectiveEntityGraph holds the entity graph currently applied to a session's load plans. applyGraph(graph, semantic) calls verifyWriteability(), which refuses to install a second graph while a semantic is already set and the instance was created with allowOverwrite=false (the default constructor used by LoadQueryInfluencers). The IllegalStateException prevents two conflicting fetch strategies from being silently stacked on one session.
Solutions
- Call effectiveEntityGraph.clear() (or verify and clear first) before applying the new graph
- Prefer per-operation graphs (find()/query hints jakarta.persistence.fetchgraph/loadgraph, or query.applyGraph) which Hibernate resets automatically
- If intentional re-application is needed, construct/use an EffectiveEntityGraph with allowOverwrite=true rather than fighting the guard
Example fix
// before var eg = ((SessionImplementor) session).getLoadQueryInfluencers().getEffectiveEntityGraph(); eg.applyGraph(orderGraph, GraphSemantic.FETCH); eg.applyGraph(userGraph, GraphSemantic.FETCH); // IllegalStateException // after var eg = ((SessionImplementor) session).getLoadQueryInfluencers().getEffectiveEntityGraph(); eg.clear(); eg.applyGraph(userGraph, GraphSemantic.FETCH);
Defensive patterns
Strategy: validation
Validate before calling
var eg = ((SessionImplementor) session).getLoadQueryInfluencers().getEffectiveEntityGraph(); eg.clear(); // no-op when nothing is applied eg.applyGraph(graph, GraphSemantic.FETCH);
Try / catch
try {
eg.applyGraph(graph, semantic);
} catch (IllegalStateException e) {
if (e.getMessage() != null && e.getMessage().contains("Cannot overwrite existing state")) {
eg.clear();
eg.applyGraph(graph, semantic); // retry once after clearing
} else {
throw e;
}
} Prevention
- Always pair session-level applyGraph with clear() when the operation ends (try/finally)
- Prefer per-query graphs (hints, query.applyGraph) over session-level effective-graph state
- Never assume the effective graph is empty in a shared/long-lived session — clear before applying
When it happens
Trigger: Calling applyGraph() twice on the session's effective entity graph without an intervening clear(): e.g. ((SessionImplementor) session).getLoadQueryInfluencers().getEffectiveEntityGraph().applyGraph(g, semantic) followed by another applyGraph, or LoadQueryInfluencers.applyEntityGraph(rootGraph, semantic) while a previous graph is still in effect. Per-operation APIs such as em.find(...) with hints or merge(object, loadGraph) clear the graph themselves, so this fires on the manual/session-level path.
Common situations: Reusing one long-lived Session/EntityManager and applying a different session-level entity graph per request without clearing; internal re-application of an initial graph after a temporary FETCH graph (follow-on locking) when the graph was never cleared; code migrated from per-query hints to session-level graphs.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Attribute ' ' is not a to-many association
- Attribute ' ' is not a to-one association
- Attribute ' ' is of type ' ' which is not a managed type
- Cannot mutate immutable graph node
- Cannot resolve entity class
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/db894aa2a4e7213b.
Report an issue: GitHub.
Appendix: source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java:96
* may be null, but that should generally be considered mis-use.
*
* @throws IllegalArgumentException Thrown if the semantic is null
* @throws IllegalStateException If previous state is still available (hasn't been cleared).
*/
public void applyGraph(RootGraphImplementor<?> graph, GraphSemantic semantic) {
if ( semantic == null ) {
throw new IllegalArgumentException( "Graph semantic cannot be null" );
}
verifyWriteability();
LOG.tracef( "Setting effective graph state [%s] : %s", semantic.name(), graph );
this.semantic = semantic;
this.graph = graph;
}
private void verifyWriteability() {
if ( ! allowOverwrite ) {
if ( semantic != null ) {
throw new IllegalStateException( "Cannot overwrite existing state, should clear previous state first" );
}
}
}
/**
* Apply a graph and semantic based on configuration properties or hints
* based on {@link GraphSemantic#getJakartaHintName()} for {@link GraphSemantic#LOAD} or
* {@link GraphSemantic#FETCH}.
* <p>
* The semantic is required. The graph
* may be null, but that should generally be considered mis-use.
*
* @throws IllegalArgumentException If both kinds of graphs were present in the properties/hints
* @throws IllegalStateException If previous state is still available (hasn't been cleared).
*/
public void applyConfiguredGraph(@Nullable Map<String,?> properties) {
if ( properties != null && !properties.isEmpty() ) {
var fetchHint = (RootGraphImplementor<?>) properties.get( HINT_JAVAEE_FETCH_GRAPH );View on GitHub (pinned to fad1729dce)