hibernate/hibernate-orm · error · IllegalArgumentException

Invalid entity-graph definition '%s'; expected form '${Entit

Error message

Invalid entity-graph definition '%s'; expected form '${EntityName}( ${property1} ... )'

What it means

Thrown by AbstractCommonQueryContract.parseGraph (line 685-692) when an inline entity-graph string has no '(' or no ')' — the parser requires the strict form '${EntityName}( ${property1} ... )' and locates the entity by the text before the first '(' via MappingMetamodel.getImportedName. Note: when parseGraph is invoked through applyEntityGraphHint's string branch, its IllegalArgumentException is caught and rethrown with the broader GraphParser message of error 2361; this exact message surfaces on paths that call/override parseGraph directly.

Source

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

				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(
					String.format(
							ROOT,
							"Invalid entity-graph definition '%s'; expected form '${EntityName}( ${property1} ... )'",
							graphString
					)
			);
		}

		final var factory = getSessionFactory();

		final String entityName =
				factory.getMappingMetamodel()
						.getImportedName( graphString.substring( 0, separatorPosition ).trim() );
		final String graphNodes = graphString.substring( separatorPosition + 1, terminatorPosition );

		final var rootGraph = new RootGraphImpl<>( null, factory.getJpaMetamodel().entity( entityName ) );
		GraphParser.parseInto( (EntityGraph<?>) rootGraph, graphNodes, getSessionFactory() );
		return rootGraph;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Format the string as 'EntityName( attr1, attr2 )' with matching parentheses, e.g. "Order( items, customer )"
  2. If you only want a named graph, make sure it is registered under that name via @NamedEntityGraph instead of an inline string
  3. Prefer passing the EntityGraph object or its registered name to avoid string parsing entirely

Example fix

// before
query.setHint( QueryHints.HINT_FETCHGRAPH, "order.items" ); // no '(' ')' -> invalid definition

// after
query.setHint( QueryHints.HINT_FETCHGRAPH, "Order( items )" );
Defensive patterns

Strategy: validation

Validate before calling

static boolean isInlineGraphForm(String s) {
    int open = s.indexOf( '(' );
    int close = s.lastIndexOf( ')' );
    return open > 0 && close > open; // 'EntityName( attr ... )'
}
// use only when isInlineGraphForm(graphString) is true

Prevention

When it happens

Trigger: A fetchgraph hint string like "Order" or "order.items" (bare name/attribute path, no parentheses and no property list) reaching parseGraph. An unterterminated graph such as "Order(items" (missing ')') or ")Order(" where lastIndexOf(')') is -1. Subclasses or user code calling the protected parseGraph(String) with a malformed string.

Common situations: Trying to reference a named graph but forgetting it must exist as @NamedEntityGraph (the inline syntax always needs parentheses); hand-building graph strings from templates; version migrations where older releases tolerated attribute-only strings.

Related errors


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