hibernate/hibernate-orm · error · SemanticException

Expected insert attribute count [%d] did not match Query sel

Error message

Expected insert attribute count [%d] did not match Query selection count [%d]

What it means

AbstractSqmInsertStatement.verifyInsertTypesMatch throws SemanticException when the number of insertion target paths (the attribute list in `insert into Entity (a, b)`) does not equal the number of expressions in the source SELECT list or VALUES rows. SQL INSERT requires a 1:1 mapping between target columns and source expressions; Hibernate enforces this during SQM semantic analysis, before any SQL is generated, so the mismatch fails fast at createQuery/parse time.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/AbstractSqmInsertStatement.java:88

			final List<SqmPath<?>> insertionTargetPaths = new ArrayList<>( this.insertionTargetPaths.size() );
			for ( SqmPath<?> insertionTargetPath : this.insertionTargetPaths ) {
				insertionTargetPaths.add( insertionTargetPath.copy( context ) );
			}
			return insertionTargetPaths;
		}
	}

	void setConflictClause(SqmConflictClause<T> conflictClause) {
		this.conflictClause = conflictClause;
	}

	protected void verifyInsertTypesMatch(
			List<SqmPath<?>> insertionTargetPaths,
			List<? extends SqmTypedNode<?>> expressions) {
		final int size = insertionTargetPaths.size();
		final int expressionsSize = expressions.size();
		if ( size != expressionsSize ) {
			throw new SemanticException(
					String.format(
							"Expected insert attribute count [%d] did not match Query selection count [%d]",
							size,
							expressionsSize
					),
					null,
					null
			);
		}

		for ( int i = 0; i < expressionsSize; i++ ) {
			final SqmTypedNode<?> expression = expressions.get( i );
			final SqmPath<?> targetPath = insertionTargetPaths.get(i);
			assertAssignable( null, targetPath, expression, nodeBuilder() );
//			if ( expression.getNodeJavaType() == null ) {
//				continue;
//			}
//			if ( insertionTargetPaths.get( i ).getJavaTypeDescriptor() != expression.getNodeJavaType() ) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Count and align: make the parenthesized attribute list and the select/values expression list the same length
  2. For INSERT ... VALUES, give every target attribute exactly one value expression in the same order
  3. For criteria inserts, check `insert.getInsertionTargetPaths().size() == source.getSelectionList().size()` before attaching the select
  4. If you intentionally omit columns, remove them from the target list rather than the values (or use defaults)

Example fix

// before
insert into Person (id, name) select p.id, p.name, p.age from PersonBackup p

// after
insert into Person (id, name, age) select p.id, p.name, p.age from PersonBackup p
Defensive patterns

Strategy: validation

Validate before calling

int targets = insertionTargetPaths.size();
int sources = selectQuery.getSelectionList().size(); // or valuesRow.size()
if (targets != sources) {
    throw new IllegalArgumentException("Insert needs " + targets + " expressions but select supplies " + sources);
}

Try / catch

try {
    session.createQuery(hql).executeUpdate();
} catch (org.hibernate.query.SemanticException e) {
    // message contains both counts; align the lists and retry once at build time is a bug — fix the query
    throw e;
}

Prevention

When it happens

Trigger: HQL `insert into Person (name, age) select p.name, p.age, p.salary from ...` (2 targets, 3 select items); `insert into Person (name, age) values (:n, :a, :x)` (3 values); criteria: `insert.setInsertionTargetPaths(root.get("name"), root.get("age"))` while the source query selects 3 items, or 3 target paths against a 2-column select.

Common situations: Editing a select list without updating the column list (or vice versa) during refactors; adding a column to the entity and forgetting the insert statement; generated SQL/DSL builders that render target list and select list from separate templates; copy-pasting an insert from another entity with a different attribute count.

Related errors


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