hibernate/hibernate-orm · error · SemanticException

Can't use expression '" + expression + " without explicit na

Error message

Can't use expression '" + expression + " without explicit name in xmlforest function, because XML element names can only be derived from path expressions.

What it means

The xmlforest(criteria) function builds XML fragments where every element needs a name. A name can only be derived automatically from a path over a persistent attribute (SqmPath whose model is a PersistentAttribute); any other expression (literal, aggregate, arithmetic, subquery, parameter) must carry an explicit name by being an SqmNamedExpression. Otherwise Hibernate throws SemanticException because it cannot invent a valid XML element name.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java:6578

	public <T> SqmExpression<T> named(Expression<T> expression, String name) {
		return new SqmNamedExpression<>( (SqmExpression<T>) expression, name );
	}

	@Override
	public SqmExpression<String> xmlforest(Expression<?>... elements) {
		return xmlforest( asList( elements ) );
	}

	@Override
	public SqmExpression<String> xmlforest(List<? extends Expression<?>> elements) {
		final ArrayList<SqmExpression<?>> arguments = new ArrayList<>( elements.size() );
		for ( Expression<?> expression : elements ) {
			if ( expression instanceof SqmNamedExpression<?> ) {
				arguments.add( (SqmNamedExpression<?>) expression );
			}
			else {
				if ( !( expression instanceof SqmPath<?> path ) || !( path.getModel() instanceof PersistentAttribute<?, ?> attribute ) ) {
					throw new SemanticException(
							"Can't use expression '" + expression + " without explicit name in xmlforest function"+
									", because XML element names can only be derived from path expressions."
					);
				}
				arguments.add( new SqmNamedExpression<>( (SqmExpression<?>) expression, attribute.getName() ) );
			}
		}
		return getFunctionDescriptor( "xmlforest" ).generateSqmExpression(
				arguments,
				null,
				queryEngine
		);
	}

	@Override
	public SqmExpression<String> xmlconcat(Expression<?>... elements) {
		return xmlconcat( asList( elements ) );
	}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Attach an explicit name to computed elements using the alias support so they become named expressions: cb.xmlforest(root.get("name"), cb.count(...).alias("order_count")) or your builder's named wrapper (SqmNamedExpression via alias()).
  2. Restrict automatically named elements to direct attribute paths (root.get("attr")).
  3. If alias() alone doesn't register as a named expression in your version, project through cb.concat/xmlforest with explicit xmlserialize/xmlconcat names or use HQL 'xmlforest(name as x, ...)' with aliases.

Example fix

// before
Expression<Long> cnt = cb.count(orderRoot.get("id"));
cb.xmlforest(customer.get("name"), cnt); // cnt is not a path -> SemanticException

// after
Expression<Long> cnt = cb.count(orderRoot.get("id")).alias("orderCount"); // explicit name
cb.xmlforest(customer.get("name"), cnt);
Defensive patterns

Strategy: validation

Validate before calling

boolean canAutoName(Expression<?> e) {
    return e instanceof Path<?> p && p.getModel() instanceof Attribute<?, ?>;
}
// every non-path element must be named:
if (!canAutoName(e) && e.getAlias() == null) throw new IllegalArgumentException("element needs explicit alias/name");

Type guard

static boolean xmlforestSafe(Expression<?> e) {
    return (e instanceof Path<?> p && p.getModel() instanceof Attribute<?, ?>)
            || e.getAlias() != null; // aliased expressions carry a name
}

Try / catch

try {
    x = cb.xmlforest(elements);
} catch (SemanticException e) {
    if (e.getMessage().contains("xmlforest")) { /* alias each computed element and rebuild */ }
    else throw e;
}

Prevention

When it happens

Trigger: cb.xmlforest(root.get("name"), cb.count(rootJoin.get("id"))) — the count() has no attribute name; passing literals (cb.literal(42)), coalesce/case expressions, or alias-less function results; calling xmlforest(Expression...) with values produced by helper builders that never call alias().

Common situations: Porting SQL 'xmlforest(...)' projections that mix columns and computed values; report builders generating XML output where aggregates like sum()/count() are added without labels; XML export features on PostgreSQL.

Related errors


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