hibernate/hibernate-orm · error · IllegalArgumentException
Passed properties contained both a LOAD and a FETCH graph wh
Error message
Passed properties contained both a LOAD and a FETCH graph which is illegal - only one should be passed
What it means
EffectiveEntityGraph.applyConfiguredGraph() inspects a properties/hints map for the four graph hint keys (javax/jakarta persistence fetchgraph and loadgraph). A fetch graph and a load graph apply contradictory semantics to the same operation, so supplying both is rejected with IllegalArgumentException.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/engine/spi/EffectiveEntityGraph.java:126
*
* @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 );
var loadHint = (RootGraphImplementor<?>) properties.get( HINT_JAVAEE_LOAD_GRAPH );
if ( fetchHint == null ) {
fetchHint = (RootGraphImplementor<?>) properties.get( HINT_SPEC_FETCH_GRAPH );
}
if ( loadHint == null ) {
loadHint = (RootGraphImplementor<?>) properties.get( HINT_SPEC_LOAD_GRAPH );
}
if ( fetchHint != null ) {
if ( loadHint != null ) {
// can't have both
throw new IllegalArgumentException(
"Passed properties contained both a LOAD and a FETCH graph which is illegal - " +
"only one should be passed"
);
}
applyGraph( fetchHint, GraphSemantic.FETCH );
}
else if ( loadHint != null ) {
applyGraph( loadHint, GraphSemantic.LOAD );
}
}
}
public void clear() {
semantic = null;
graph = null;
}
public void withAppliedGraph(GraphSemantic semantic, RootGraphImplementor<?> graph, Runnable action) {View on GitHub (pinned to fad1729dce)
Solutions
- Remove one of the two hints so the map contains only a fetchgraph or only a loadgraph
- Sanitize merged hint maps before use: strip the unused key after merging
- Standardize on one spelling (jakarta.persistence.*) and audit shared hint maps for stray javax keys
Example fix
// before
Map<String, Object> hints = new HashMap<>();
hints.put("jakarta.persistence.fetchgraph", fetchGraph);
hints.put("jakarta.persistence.loadgraph", loadGraph); // both present -> IllegalArgumentException
em.find(Order.class, id, hints);
// after
Map<String, Object> hints = new HashMap<>();
hints.put("jakarta.persistence.fetchgraph", fetchGraph);
em.find(Order.class, id, hints); Defensive patterns
Strategy: validation
Validate before calling
private static final Set<String> GRAPH_HINT_KEYS = Set.of(
"jakarta.persistence.fetchgraph", "jakarta.persistence.loadgraph",
"javax.persistence.fetchgraph", "javax.persistence.loadgraph");
static void assertSingleGraphHint(Map<String, Object> hints) {
List<String> present = GRAPH_HINT_KEYS.stream()
.filter(hints::containsKey).toList();
if (present.size() > 1) {
throw new IllegalArgumentException("Pass only one entity-graph hint, found: " + present);
}
} Try / catch
try {
em.find(Order.class, id, hints);
} catch (IllegalArgumentException e) {
if (String.valueOf(e.getMessage()).contains("both a LOAD and a FETCH graph")) {
hints.remove("jakarta.persistence.loadgraph"); // keep fetchgraph only
em.find(Order.class, id, hints);
} else {
throw e;
}
} Prevention
- Centralize hint-map construction in one helper so both keys can never be added
- When merging hint maps, remove graph-hint keys from the loser before merging
- Pick one family (jakarta.* or javax.*) and forbid the other via a build-time check
When it happens
Trigger: Passing a properties map that contains both HINT_SPEC/JAVAEE_FETCH_GRAPH and HINT_SPEC/JAVAEE_LOAD_GRAPH (any mix of 'jakarta.persistence.fetchgraph', 'jakarta.persistence.loadgraph', 'javax.persistence.fetchgraph', 'javax.persistence.loadgraph') to an API that feeds applyConfiguredGraph(), such as EntityManager.find(cls, id, hints), session find-by-key operations, or Query hint processing.
Common situations: Hint maps assembled by merging defaults with per-call overrides (framework or utility code) without removing the losing key; javax-to-jakarta migration where both spellings get added; Spring Data JPA @EntityGraph combined with manually put graph hints; copy-pasting hint constants between call sites.
Related errors
- Graph semantic specified, but no RootGraph was supplied
- Informix only supports the case insensitive flag 'i' as lite
- Duplicate named entity graph '%s'
- The 'root' parameter of the @NamedEntityGraph should be pass
- The 'root' parameter of the @NamedEntityGraph annotation mus
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/348946f3c46313b1.
Report an issue: GitHub.