{"record":{"id":"629cf445f22d0ef7","repo":"hibernate/hibernate-orm","slug":"expected-insert-attribute-count-d-did-not-match","errorCode":null,"errorMessage":"Expected insert attribute count [%d] did not match Query selection count [%d]","messagePattern":"Expected insert attribute count \\[(.+?)\\] did not match Query selection count \\[(.+?)\\]","errorType":"exception","errorClass":"SemanticException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/AbstractSqmInsertStatement.java","lineNumber":88,"sourceCode":"\t\t\tfinal List<SqmPath<?>> insertionTargetPaths = new ArrayList<>( this.insertionTargetPaths.size() );\n\t\t\tfor ( SqmPath<?> insertionTargetPath : this.insertionTargetPaths ) {\n\t\t\t\tinsertionTargetPaths.add( insertionTargetPath.copy( context ) );\n\t\t\t}\n\t\t\treturn insertionTargetPaths;\n\t\t}\n\t}\n\n\tvoid setConflictClause(SqmConflictClause<T> conflictClause) {\n\t\tthis.conflictClause = conflictClause;\n\t}\n\n\tprotected void verifyInsertTypesMatch(\n\t\t\tList<SqmPath<?>> insertionTargetPaths,\n\t\t\tList<? extends SqmTypedNode<?>> expressions) {\n\t\tfinal int size = insertionTargetPaths.size();\n\t\tfinal int expressionsSize = expressions.size();\n\t\tif ( size != expressionsSize ) {\n\t\t\tthrow new SemanticException(\n\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\"Expected insert attribute count [%d] did not match Query selection count [%d]\",\n\t\t\t\t\t\t\tsize,\n\t\t\t\t\t\t\texpressionsSize\n\t\t\t\t\t),\n\t\t\t\t\tnull,\n\t\t\t\t\tnull\n\t\t\t);\n\t\t}\n\n\t\tfor ( int i = 0; i < expressionsSize; i++ ) {\n\t\t\tfinal SqmTypedNode<?> expression = expressions.get( i );\n\t\t\tfinal SqmPath<?> targetPath = insertionTargetPaths.get(i);\n\t\t\tassertAssignable( null, targetPath, expression, nodeBuilder() );\n//\t\t\tif ( expression.getNodeJavaType() == null ) {\n//\t\t\t\tcontinue;\n//\t\t\t}\n//\t\t\tif ( insertionTargetPaths.get( i ).getJavaTypeDescriptor() != expression.getNodeJavaType() ) {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/insert/AbstractSqmInsertStatement.java#L70-L106","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Count and align: make the parenthesized attribute list and the select/values expression list the same length","For INSERT ... VALUES, give every target attribute exactly one value expression in the same order","For criteria inserts, check `insert.getInsertionTargetPaths().size() == source.getSelectionList().size()` before attaching the select","If you intentionally omit columns, remove them from the target list rather than the values (or use defaults)"],"exampleFix":"// before\ninsert into Person (id, name) select p.id, p.name, p.age from PersonBackup p\n\n// after\ninsert into Person (id, name, age) select p.id, p.name, p.age from PersonBackup p","handlingStrategy":"validation","validationCode":"int targets = insertionTargetPaths.size();\nint sources = selectQuery.getSelectionList().size(); // or valuesRow.size()\nif (targets != sources) {\n    throw new IllegalArgumentException(\"Insert needs \" + targets + \" expressions but select supplies \" + sources);\n}","typeGuard":null,"tryCatchPattern":"try {\n    session.createQuery(hql).executeUpdate();\n} catch (org.hibernate.query.SemanticException e) {\n    // message contains both counts; align the lists and retry once at build time is a bug — fix the query\n    throw e;\n}","preventionTips":["Keep target attribute list and select/values list in one place (single template or builder method)","Add a startup/unit test that parses every static insert statement","When adding an entity column, grep all insert-into statements for that entity"],"tags":["hibernate","hql","insert","column-count","semantic-error","criteria-api"],"backgroundTag":"sql-column-count-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}