hibernate/hibernate-orm · error · IllegalStateException

There must be at least a single root table assignment

Error message

There must be at least a single root table assignment

What it means

CteInsertHandler requires at least one assignment into the entity's ROOT table. The check fires when the statement doesn't assign the id (assignsId == false), the id generator is not generated-on-execution (i.e., manually assigned ids), AND no assignments target the root table — leaving no valid root-table INSERT to emit. It's an IllegalStateException raised during query translation.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertHandler.java:718

		}


		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Add the root insert as cte


		final String rootTableName = entityPersister.getTableName( 0 );
		final TableReference rootTableReference = updatingTableGroup.getTableReference(
				updatingTableGroup.getNavigablePath(),
				rootTableName,
				true
		);

		final Generator identifierGenerator = entityPersister.getGenerator();
		final List<Map.Entry<List<CteColumn>, Assignment>> tableAssignments = assignmentsByTable.get( rootTableReference );
		if ( !assignsId && ( tableAssignments == null || tableAssignments.isEmpty() )
				&& !identifierGenerator.generatedOnExecution() ) {
			throw new IllegalStateException( "There must be at least a single root table assignment" );
		}

		final ConflictClause conflictClause = sqmConverter.visitConflictClause( sqmStatement.getConflictClause() );

		final int tableSpan = entityPersister.getTableSpan();
		final List<CteColumn> keyCteColumns = queryCte.getCteTable().findCteColumns( entityPersister.getIdentifierMapping() );
		for ( int tableIndex = 0; tableIndex < tableSpan; tableIndex++ ) {
			final String tableExpression = entityPersister.getTableName( tableIndex );
			final TableReference updatingTableReference = updatingTableGroup.getTableReference(
					updatingTableGroup.getNavigablePath(),
					tableExpression,
					true
			);
			final List<Map.Entry<List<CteColumn>, Assignment>> assignmentList = assignmentsByTable.get( updatingTableReference );
			final NamedTableReference dmlTableReference = resolveUnionTableReference(
					updatingTableReference,
					tableExpression
			);

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add the id attribute to the target list: `insert into SubType(id, name)`
  2. If ids should be database/sequence generated, configure @GeneratedValue on the id
  3. Ensure at least one root-table attribute appears in the insert column list

Example fix

// before
insert into Region(code, name)
select c.code, c.name from Country c

// after (id is manually assigned)
insert into Region(id, code, name)
select c.id, c.code, c.name from Country c
Defensive patterns

Strategy: validation

Validate before calling

// Before executing insert...select, require the id (or a root column) in the target list
EntityType<?> et = em.getMetamodel().entity(Region.class);
if (!assignsGeneratedId(Region.class)
        && !targetColumns.contains(et.getDeclaredId(targetIdType).getName())) {
    throw new IllegalArgumentException(
        "Insert target list must include the assigned id attribute");
}

Try / catch

try {
    em.createQuery(insertHql).executeUpdate();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("root table assignment")) {
        throw new QueryBuildException("Add the id (or a root-table column) to the insert list", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: `insert into SubType(name) select ...` where SubType has a hand-assigned @Id (no @GeneratedValue) and every listed attribute belongs to a subclass/secondary table; omitting the id attribute from the insert target column list of an entity with assigned identifiers.

Common situations: HQL insert...select on entities with manually assigned or client-provided ids where the author forgot the id column; joined-inheritance inserts listing only subclass fields; legacy @Id mappings without generators being used with bulk insert statements.

Related errors


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