hibernate/hibernate-orm · error · IllegalArgumentException

Illegal cycle attribute '{}' passed, which is not part of th

Error message

Illegal cycle attribute '{}' passed, which is not part of the JpaCteCriteria!

What it means

The cycle(...) overload also validates every entry of cycleAttributes against cteTable.getAttributes(); only attributes that are columns of the CTE type itself may be used for cycle detection. Passing an entity attribute from the base query (or an attribute of another CTE) throws IllegalArgumentException naming the offending attribute.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/cte/SqmCteStatement.java:322

			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;
			this.cyclePathAttributeName = cyclePathAttributeName;
			this.cycleValue = (SqmLiteral<Object>) cycleValueLiteral;
			this.noCycleValue = (SqmLiteral<Object>) noCycleValueLiteral;
			this.cycleAttributes = attributes;
		}
	}

	@Override
	public <X> X accept(SemanticQueryWalker<X> walker) {
		return walker.visitCteStatement( this );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pass only attributes of the CTE type obtained from the JpaCteCriteria created by with(...).
  2. Resolve columns by name via the CTE type's getAttribute(name).
  3. If a needed column is missing from the CTE, select it in the CTE's base query first so it becomes a CTE attribute.

Example fix

// before
cte.cycle( "isCycle", "path", true, false, List.of( personRoot.getModelfield() ) ); // entity attribute
// after
List<JpaCteCriteriaAttribute> cols = List.of( /* attributes of the CTE type from with(...) */ );
cte.cycle( "isCycle", "path", true, false, cols );
Defensive patterns

Strategy: validation

Validate before calling

List<JpaCteCriteriaAttribute> ok = cycleColumns.stream()
    .filter( a -> cteType.getAttributes().contains( a ) )
    .toList();
if ( ok.size() != cycleColumns.size() ) {
    throw new IllegalArgumentException( "Some cycle columns are not CTE attributes" );
}
cte.cycle( "isCycle", "path", true, false, ok );

Type guard

static boolean isCteAttribute(JpaCteCriteriaType<?> type, JpaCteCriteriaAttribute a) {
    return type.getAttributes().contains( a );
}

Prevention

When it happens

Trigger: cte.cycle("isCycle", "path", true, false, List.of(baseRootAttr)) where baseRootAttr is a SingularAttribute/Path of the underlying entity instead of a JpaCteCriteriaAttribute of the CTE type.

Common situations: Converting HQL 'CYCLE id SET ...' to criteria and reusing the entity metamodel attribute instead of the CTE attribute; building cycle clauses in generic helpers that receive entity attributes.

Related errors


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