hibernate/hibernate-orm · error · IllegalArgumentException

The string value of the hint '{hintName}' must be the name o

Error message

The string value of the hint '{hintName}' must be the name of a named EntityGraph, or a representation understood by GraphParser

What it means

Thrown when a fetchgraph/loadgraph hint ('jakarta.persistence.fetchgraph' or 'jakarta.persistence.loadgraph') receives a String value that is neither the name of a registered @NamedEntityGraph nor a string Hibernate's GraphParser understands. AbstractCommonQueryContract.applyEntityGraphHint (line ~654) first tries session.getEntityGraph(string); if that lookup fails it calls parseGraph(string) inside a try, and any IllegalArgumentException from either step is rethrown with this combined message at line 668.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/internal/AbstractCommonQueryContract.java:668

			applyGraph( rootGraphImplementor, graphSemantic );
		}
		else if ( value instanceof String string ) {
			// try and interpret it as the name of a @NamedEntityGraph
			try {
				applyGraph( getSession().getEntityGraph( string ), graphSemantic );
				// getEntityGraph throws an exception if not found.  but since we got here, it was found
				return;
			}
			catch (IllegalArgumentException ignore) {
				// fall through...
			}

			// try and parse it in the entity graph language
			try {
				applyGraph( parseGraph( string ), graphSemantic );
			}
			catch ( IllegalArgumentException e ) {
				throw new IllegalArgumentException( "The string value of the hint '" + hintName
													+ "' must be the name of a named EntityGraph, or a representation understood by GraphParser" );
			}
		}
		else {
			throw new IllegalArgumentException( "The value of the hint '" + hintName
												+ "' must be an instance of EntityGraph, the string name of a named EntityGraph, or a string representation understood by GraphParser" );
		}
	}

	protected void applyEnabledFetchProfileHint(String hintName, Object value) {
		queryOptions.enableFetchProfile( (String) value );
	}

	protected RootGraphImplementor<?> parseGraph(String graphString) {
		final int separatorPosition = graphString.indexOf( '(' );
		final int terminatorPosition = graphString.lastIndexOf( ')' );
		if ( separatorPosition < 0 || terminatorPosition < 0 ) {
			throw new IllegalArgumentException(

View on GitHub (pinned to fad1729dce)

Solutions

  1. Fix the name to match the @NamedEntityGraph name exactly, or register the graph first: em.createEntityGraph / @NamedEntityGraph on the entity
  2. If you meant an inline graph, use the exact form 'EntityName( attribute1, attribute2 )' with the entity's Hibernate name (imported name) and real attribute names
  3. Prefer passing the EntityGraph object itself: query.setHint(HINT_FETCHGRAPH, em.getEntityGraph("orderGraph")) — this bypasses both lookup and parsing
  4. List available graph names via session.getFactory().getNamedEntityGraphs().keySet() to verify what is registered

Example fix

// before
query.setHint( QueryHints.HINT_FETCHGRAPH, "order-with-itmes" ); // typo -> IllegalArgumentException

// after
query.setHint( QueryHints.HINT_FETCHGRAPH, em.getEntityGraph( "order-with-items" ) );
// or inline form:
query.setHint( QueryHints.HINT_FETCHGRAPH, "Order( items, customer )" );
Defensive patterns

Strategy: validation

Validate before calling

if ( value instanceof String name ) {
    boolean registered = em.getEntityManagerFactory().getNamedEntityGraphs().stream()
            .anyMatch( holder -> holder.getName().equals( name ) );
    boolean parseable = name.indexOf( '(' ) >= 0 && name.lastIndexOf( ')' ) >= 0;
    if ( !registered && !parseable ) throw new IllegalStateException( "Unknown entity graph: " + name );
}
query.setHint( QueryHints.HINT_FETCHGRAPH, value );

Type guard

static boolean isResolvableGraphHint(Object v, EntityManager em) {
    if ( v instanceof EntityGraph<?> ) return true;
    if ( v instanceof String s ) {
        try { em.getEntityGraph( s ); return true; }
        catch ( IllegalArgumentException ignore ) { return s.indexOf( '(' ) >= 0 && s.lastIndexOf( ')' ) >= 0; }
    }
    return false;
}

Try / catch

try {
    query.setHint( QueryHints.HINT_FETCHGRAPH, graphRef );
} catch ( IllegalArgumentException e ) {
    // fall back to no graph (default fetching) instead of failing the request
    log.warn( "Unresolvable entity graph '{}', continuing without graph", graphRef );
}

Prevention

When it happens

Trigger: query.setHint("jakarta.persistence.fetchgraph", "orderGrapf") where the @NamedEntityGraph is actually named "orderGraph" (typo). Passing a graph string that is not parseable, e.g. "order.items" without parentheses, "Order( nonExistentAttr )" with an unknown attribute, or an entity prefix that is not a known/imported entity name so factory.getMappingMetamodel().getImportedName fails.

Common situations: Typos in named-graph names; assuming JPQL join paths or JPA attribute names work as inline graph strings; graph defined in a different persistence unit or registered via a different SessionFactory; migrating code that used the legacy javax.persistence.fetchgraph key whose handling now flows through the same parser; entity mapped under an entity name (@Entity(name=...)) so the class name prefix doesn't resolve.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/3890b3b80f7c27d9. Report an issue: GitHub.