hibernate/hibernate-orm · error · IllegalArgumentException
Null is an illegal value for cycle mark values!
Error message
Null is an illegal value for cycle mark values!
What it means
The full cycle(...) overload on SqmCteStatement converts cycleValue/noCycleValue into SQM literals via nodeBuilder().literal(...); when a cycle clause is being defined (cycleMarkAttributeName non-null, attributes non-empty) but either mark value is null, it throws IllegalArgumentException. Null cannot be a cycle mark literal, both the cycle and the no-cycle value must be supplied.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/cte/SqmCteStatement.java:312
}
@Override
public <X> void cycleUsing(
String cycleMarkAttributeName,
String cyclePathAttributeName,
X cycleValue,
X noCycleValue,
List<JpaCteCriteriaAttribute> cycleAttributes) {
if ( cycleMarkAttributeName == null || cycleAttributes == null || cycleAttributes.isEmpty() ) {
this.cycleMarkAttributeName = null;
this.cyclePathAttributeName = null;
this.cycleValue = null;
this.noCycleValue = null;
this.cycleAttributes = Collections.emptyList();
}
else {
if ( cycleValue == null || noCycleValue == null ) {
throw new IllegalArgumentException( "Null is an illegal value for cycle mark values!" );
}
final SqmExpression<X> cycleValueLiteral = nodeBuilder().literal( cycleValue );
final SqmExpression<X> noCycleValueLiteral = nodeBuilder().literal( noCycleValue );
if ( cycleValueLiteral.getNodeType() != noCycleValueLiteral.getNodeType() ) {
throw new IllegalArgumentException( "Inconsistent types for cycle mark values: [" + cycleValueLiteral.getNodeType() + ", " + noCycleValueLiteral.getNodeType() + "]" );
}
final List<SqmCteTableColumn> attributes = new ArrayList<>( cycleAttributes.size() );
for ( JpaCteCriteriaAttribute cycleAttribute : cycleAttributes ) {
if ( !cteTable.getAttributes().contains( cycleAttribute ) ) {
throw new IllegalArgumentException(
"Illegal cycle attribute '" +
( cycleAttribute == null ? "null" : cycleAttribute.getName() ) +
"' passed, which is not part of the JpaCteCriteria!"
);
}
attributes.add( (SqmCteTableColumn) cycleAttribute );
}
this.cycleMarkAttributeName = cycleMarkAttributeName;View on GitHub (pinned to fad1729dce)
Solutions
- Pass explicit non-null mark values of one type, e.g. true/false, 1/0 or "T"/"F".
- If defaults are fine, use the shorter overloads cycle(cycleMarkAttributeName, cycleColumns) / cycleUsing(...) which do not take mark values.
Example fix
// before cte.cycle( "isCycle", "path", null, null, columns ); // null mark values // after cte.cycle( "isCycle", "path", true, false, columns );
Defensive patterns
Strategy: validation
Validate before calling
Objects.requireNonNull( cycleValue, "cycleValue" ); Objects.requireNonNull( noCycleValue, "noCycleValue" ); cte.cycle( "isCycle", "path", cycleValue, noCycleValue, columns );
Prevention
- Default to a canonical pair such as true/false instead of nulls.
- Use the short cycle(cycleMarkAttributeName, cycleColumns)/cycleUsing overloads when default marks suffice.
- Treat null as 'clause not wanted' only by skipping the cycle() call entirely.
When it happens
Trigger: cte.cycle("isCycle", "path", null, null, columns), or cte.cycle("isCycle", "path", true, null, columns) on a recursive CTE created with withRecursiveUnionAll/Distinct.
Common situations: Trying to let the database use defaults by passing nulls; refactoring from the short cycle(String, JpaCteCriteriaAttribute...) overload to the full one and forgetting to fill in the mark values.
Related errors
- Illegal cycle attribute '{}' passed, which is not part of th
- Illegal search order attribute '{}' passed, which is not par
- Inconsistent types for cycle mark values: [{}, {}]
- Illegal empty CTE name
- Illegal CTE name [%s]. Names must start with an alphabetic c
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4bc183f743e0b9de.
Report an issue: GitHub.