hibernate/hibernate-orm · error · IllegalStateException
Mismatch between generated column values and identifier colu
Error message
Mismatch between generated column values and identifier columns for %s
What it means
For identifiers generated on execution (OnExecutionGenerator - identity-like generation, database functions or triggers assigning the PK), InsertCoordinatorStandard applies the generator's column inclusions and referenced column values to the key columns. IllegalStateException 'Mismatch between generated column values and identifier columns' means getReferencedColumnValues(dialect, INSERT) returned an array whose length differs from the identifier column count of the table.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/InsertCoordinatorStandard.java:576
entityPersister().addDiscriminatorToInsertGroup( insertGroupBuilder );
entityPersister().addAuxiliaryToInsertGroup( insertGroupBuilder );
// add the keys
insertGroupBuilder.forEachTableMutationBuilder( (tableMutationBuilder) -> {
final var tableInsertBuilder = (TableInsertBuilder) tableMutationBuilder;
final var tableMapping = (EntityTableMapping) tableInsertBuilder.getMutatingTable().getTableMapping();
final var keyMapping = tableMapping.getKeyMapping();
if ( tableMapping.isIdentifierTable()
&& entityPersister().isIdentifierAssignedByInsert()
&& !forceIdentifierBinding ) {
assert entityPersister().getInsertDelegate() != null;
final var generator = (OnExecutionGenerator) entityPersister().getGenerator();
final boolean[] columnInclusions = generator.getColumnInclusions( dialect, EventType.INSERT );
final String[] columnValues = generator.getReferencedColumnValues( dialect, EventType.INSERT );
final int keyColumnCount = keyMapping.getColumnCount();
if ( columnInclusions != null ) {
if ( columnValues != null && columnValues.length != keyColumnCount ) {
throw new IllegalStateException(
"Mismatch between generated column values and identifier columns for "
+ entityPersister().getEntityName()
);
}
for ( int i = 0; i < keyColumnCount; i++ ) {
if ( columnInclusions[i] ) {
final String valueExpression =
columnValues == null
? keyMapping.getKeyColumn( i ).getWriteExpression()
: columnValues[i];
tableInsertBuilder.addColumnAssignment( keyMapping.getKeyColumn( i ), valueExpression );
}
}
}
else if ( generator.referenceColumnsInSql( dialect, EventType.INSERT ) ) {
if ( columnValues != null ) {
assert columnValues.length == 1;
assert keyColumnCount == 1;View on GitHub (pinned to fad1729dce)
Solutions
- Return null from getReferencedColumnValues when the database assigns values via the key columns' write expressions
- Otherwise return exactly keyColumnCount values, in the same order as the key columns
- Keep getColumnInclusions length aligned with the identifier columns as well
- Add a CI insert test per generator-backed entity so contract mismatches fail at build time
Example fix
// before: values array does not match identifier column count
public class TriggerPkGenerator implements OnExecutionGenerator {
@Override
public String[] getReferencedColumnValues(Dialect d, EventType t) {
return new String[] { "gen_pk()" }; // breaks for composite keys (2 columns)
}
}
// after: let each key column use its own write expression
@Override
public String[] getReferencedColumnValues(Dialect d, EventType t) {
return null; // null -> per-column write expressions, count always matches
} Defensive patterns
Strategy: validation
Validate before calling
// unit test: generator contract must match identifier column count
@Test void generatorValuesMatchKeyColumns() {
String[] vals = generator.getReferencedColumnValues(dialect, EventType.INSERT);
int keyCols = metadata.getEntityBinding(Entity.class.getName())
.getRootTable().getPrimaryKey().getColumns().size();
assertTrue(vals == null || vals.length == keyCols,
"getReferencedColumnValues length must equal identifier column count or be null");
} Try / catch
try { session.persist(entity); tx.commit(); } catch (IllegalStateException e) { if (e.getMessage().contains("generated column values")) { /* fix generator to return null or keyColumnCount values */ } throw e; } Prevention
- Return null from getReferencedColumnValues unless you supply one value per key column
- Unit-test every custom OnExecutionGenerator against the entity's key column count
- Re-test generators when adding composite keys to generator-backed entities
When it happens
Trigger: A custom OnExecutionGenerator whose getReferencedColumnValues returns a hardcoded array shorter or longer than the key (typically written for single-column ids and reused on @EmbeddedId/@IdClass entities); returning an empty array instead of null; composite keys where only some columns get values.
Common situations: Implementing PK-by-trigger or PK-by-database-function generators; migrating an identity-style generator to a composite-key entity; Hibernate upgrades where the null-vs-array contract (null = use the key columns' write expressions) tightened.
Related errors
- Attribute '%s' of entity '%s' is mapped by association '%s'
- Duplicate generator name %s; you will likely want to set the
- Foreign key ({}:{} [{}])) must have same number of columns a
- identifier mapping has wrong number of columns: " + getEntit
- Identity generation requires exactly one column
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/67d297a721b29f1c.
Report an issue: GitHub.