hibernate/hibernate-orm · error · SchemaManagementException
Index mismatch - `%s` on table `%s`
Error message
Index mismatch - `%s` on table `%s`
What it means
Index validation found an index with the declared name, but its column list disagrees with the mapping: a different column count, or the i-th indexed column's identifier differs from the i-th selectable of the mapped index (the comparison is position-sensitive, in both directions). Hibernate requires the mapped and physical index to cover the same columns in the same order.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java:231
var indicesMatch = true;
assert index.getSelectables().size() == index.getColumnSpan();
if ( index.getColumnSpan() != indexInformation.getIndexedColumns().size() ) {
indicesMatch = false;
}
else {
for ( int i = 0; i < index.getSelectables().size(); i++ ) {
final Selectable column = index.getSelectables().get( i );
final ColumnInformation columnInfo = indexInformation.getIndexedColumns().get( i );
if ( !column.getText().equals( columnInfo.getColumnIdentifier().getText() ) ) {
indicesMatch = false;
break;
}
}
}
if ( !indicesMatch ) {
throw new SchemaManagementException(
String.format(
ROOT,
"Index mismatch - `%s` on table `%s`",
name.render( dialect ),
tableInformation.getName().render()
)
);
}
} );
}
private void validateUniqueKeys(
Table table,
TableInformation tableInformation,
Metadata metadata,
ExecutionOptions options,
Dialect dialect) {
var validationType = ConstraintValidationType.interpret( UNIQUE_KEY_VALIDATION, options.getConfigurationValues() );View on GitHub (pinned to fad1729dce)
Solutions
- Recreate the index with exactly the columns and order the mapping declares: DROP INDEX <name>; CREATE INDEX <name> ON <table> (col1, col2);
- Or update @Index(columnList=...) to match the real index definition.
- If the difference is intentional, drop the mapped declaration or disable index validation (hibernate.tooling.schema.index_validation=NONE).
Example fix
-- before: existing index covers (customer_id) but the mapping declares (customer_id, created_at) DROP INDEX orders_customer_idx; -- after: recreate to match the mapping exactly, order included CREATE INDEX orders_customer_idx ON orders (customer_id, created_at);
Defensive patterns
Strategy: validation
Validate before calling
// Before validate, compare declared column lists (order included) against JDBC index metadata
// expected: "customer_id,created_at" from @Index(columnList)
try (Connection c = dataSource.getConnection();
ResultSet rs = c.getMetaData().getIndexInfo(null, null, "orders", false, false)) {
Map<String, List<String>> byIndex = new HashMap<>();
while (rs.next()) {
String n = rs.getString("INDEX_NAME");
if (n != null) byIndex.computeIfAbsent(n, k -> new ArrayList<>()).add(rs.getString("COLUMN_NAME"));
}
List<String> actual = byIndex.get("orders_customer_idx");
if (!List.of("customer_id", "created_at").equals(actual)) {
throw new IllegalStateException("orders_customer_idx column list/order mismatch: " + actual);
}
} Try / catch
try {
new SchemaValidator().validate(metadata, serviceRegistry);
} catch (SchemaManagementException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Index mismatch")) {
// recreate the index with exactly the mapped columns/order, or update columnList to reality
}
throw e;
} Prevention
- Treat index column order as part of the API: never reorder columns without a migration and mapping update
- When DBAs tune indexes, sync the @Index declaration in the same change set
- Keep index validation enabled in CI so divergence is caught at build time
When it happens
Trigger: validate with hibernate.tooling.schema.index_validation=NAMED/ALL where an existing index covers different columns or a different order than @Index(columnList = "a, b") declares: the migration created the index on (b, a); a DBA later replaced a single-column index with a composite one; a column was renamed in the DB but the mapping kept the old name.
Common situations: Hand-tuned production indexes diverging from entity declarations; performance work adding leading columns to indexes without updating mappings; index definitions copied between MySQL and PostgreSQL exports with reordered columns.
Related errors
- Missing index named `%s` on table `%s`
- Missing unique constraint named `%s` on table `%s`
- Unique-key mismatch - `%s` on table `%s`
- Unrecognized 'hibernate.hbm2ddl.jdbc_metadata_extraction_str
- Attempt to resolve JDBC metadata failed to find columns for
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4d6ab80d106e5485.
Report an issue: GitHub.