hibernate/hibernate-orm · error · IllegalArgumentException
Illegal search order attribute '{}' passed, which is not par
Error message
Illegal search order attribute '{}' passed, which is not part of the JpaCteCriteria! What it means
SqmCteStatement.search(kind, searchAttributeName, searchOrders) validates every JpaSearchOrder's attribute against cteTable.getAttributes(): only attributes that are columns of the CTE type itself are accepted. Passing an attribute of the underlying entity (e.g. a Path from the base query's root) or of a different CTE throws IllegalArgumentException naming the offending attribute.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/cte/SqmCteStatement.java:281
@Nonnull
@Override
public JpaCteCriteriaType<T> getType() {
return cteTable;
}
@Override
public void search(CteSearchClauseKind kind, String searchAttributeName, List<JpaSearchOrder> searchOrders) {
if ( kind == null || searchAttributeName == null || searchOrders == null || searchOrders.isEmpty() ) {
this.searchClauseKind = null;
this.searchBySpecifications = Collections.emptyList();
this.searchAttributeName = null;
}
else {
final List<JpaSearchOrder> orders = new ArrayList<>( searchOrders.size() );
for ( JpaSearchOrder order : searchOrders ) {
if ( !cteTable.getAttributes().contains( order.getAttribute() ) ) {
throw new IllegalArgumentException(
"Illegal search order attribute '" +
( order.getAttribute() == null ? "null" : order.getAttribute().getName() ) +
"' passed, which is not part of the JpaCteCriteria!"
);
}
orders.add( order );
}
this.searchClauseKind = kind;
this.searchAttributeName = searchAttributeName;
//noinspection unchecked
this.searchBySpecifications = (List<SqmSearchClauseSpecification>) (List<?>) orders;
}
}
@Override
public <X> void cycleUsing(
String cycleMarkAttributeName,
String cyclePathAttributeName,View on GitHub (pinned to fad1729dce)
Solutions
- Build search orders only from the CTE type's own attributes: JpaCteCriteriaAttribute from the JpaCteCriteria returned by with(...), e.g. cb.search(cteAttribute, SortDirection.ASCENDING, Nulls.FIRST).
- Look the attribute up by name via the CTE type's getAttribute(name) instead of holding entity paths.
- Keep a reference to the attributes returned when the CTE was created and pass those into search().
Example fix
// before cte.search( DEPTH_FIRST, "seq", List.of( cb.search( baseRoot.get( "id" ) ) ) ); // not a CTE attribute // after JpaCteCriteriaAttribute idCol = /* attribute of the CTE type from with(...) */; cte.search( DEPTH_FIRST, "seq", List.of( cb.search( idCol, SortDirection.ASCENDING ) ) );
Defensive patterns
Strategy: validation
Validate before calling
// only pass orders whose attribute is one of the CTE type's own attributes
List<JpaSearchOrder> safeOrders = new ArrayList<>();
for ( JpaSearchOrder order : wantedOrders ) {
if ( cteType.getAttributes().contains( order.getAttribute() ) ) {
safeOrders.add( order );
}
}
cte.search( kind, "search", safeOrders ); Type guard
static boolean isCteAttribute(JpaCteCriteria<?> cte, JpaSearchOrder order) {
return order.getAttribute() instanceof JpaCteCriteriaAttribute
&& cte.getCteTable().getAttributes().contains( order.getAttribute() );
} Prevention
- Build JpaSearchOrder only through HibernateCriteriaBuilder.search(cteAttribute, ...).
- Keep the JpaCteCriteria returned by with(...) and take search/cycle attributes from its type, never from the entity root.
- If a base-query column is needed for ordering, make sure it is selected as a CTE column first.
When it happens
Trigger: cte.search(CteSearchClauseKind.DEPTH_FIRST, "seq", List.of(cb.search(root.get("id")))) where the JpaSearchOrder was built from the entity root instead of an attribute of the CTE type returned by with(...). Also passing an attribute of another CTE.
Common situations: Building recursive CTEs with a SEARCH clause for ordering; natural mistake of re-using base-query attributes because the CTE attributes must be fetched from the JpaCteCriteriaType (getAttributes()/getAttribute(name)) rather than the entity metamodel.
Related errors
- Null is an illegal value for cycle mark values!
- Illegal cycle attribute '{}' passed, which is not part of th
- Illegal empty CTE name
- Illegal CTE name [%s]. Names must start with an alphabetic c
- Inconsistent types for cycle mark values: [{}, {}]
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/a8010a71ed98124c.
Report an issue: GitHub.