hibernate/hibernate-orm · error · IllegalStateException
Cannot overwrite existing state, should clear previous state
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.
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)
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
- Duplicate named entity graph '%s'
- Fetch profile '{}' has a '@FetchOverride' with 'fetch=LAZY'
- The 'root' parameter of the @NamedEntityGraph should be pass
- The 'root' parameter of the @NamedEntityGraph annotation mus
- many-to-many defining filter or where without join fetching
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/db894aa2a4e7213b.
Report an issue: GitHub.