{"record":{"id":"698f26983baabdf4","repo":"hibernate/hibernate-orm","slug":"unique-key-mismatch-s-on-table-s","errorCode":null,"errorMessage":"Unique-key mismatch - `%s` on table `%s`","messagePattern":"Unique-key mismatch - `(.+?)` on table `(.+?)`","errorType":"exception","errorClass":"SchemaManagementException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java","lineNumber":297,"sourceCode":"\n\t\t\tvar matches = true;\n\t\t\tassert uk.getColumns().size() == uk.getColumnSpan();\n\t\t\tif ( uk.getColumnSpan() != ukInfo.getIndexedColumns().size() ) {\n\t\t\t\tmatches = false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfor ( int i = 0; i < uk.getColumns().size(); i++ ) {\n\t\t\t\t\tfinal Column column = uk.getColumns().get( i );\n\t\t\t\t\tfinal ColumnInformation columnInfo = ukInfo.getIndexedColumns().get( i );\n\t\t\t\t\tif ( !column.getName().equals( columnInfo.getColumnIdentifier().getText() ) ) {\n\t\t\t\t\t\tmatches = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !matches ) {\n\t\t\t\tthrow new SchemaManagementException(\n\t\t\t\t\t\tString.format(\n\t\t\t\t\t\t\t\tROOT,\n\t\t\t\t\t\t\t\t\"Unique-key mismatch - `%s` on table `%s`\",\n\t\t\t\t\t\t\t\tname.render( dialect ),\n\t\t\t\t\t\t\t\ttableInformation.getName().render()\n\t\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\t}\n\n\tprotected void validateSequence(Sequence sequence, SequenceInformation sequenceInformation) {\n\t\tif ( sequenceInformation == null ) {\n\t\t\tthrow new SchemaManagementException(\n\t\t\t\t\tString.format( \"Schema validation: missing sequence [%s]\", sequence.getName() )\n\t\t\t);\n\t\t}\n","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java#L279-L315","documentation":"Unique-key validation: an index with the declared unique-key name exists in JDBC metadata, but its column list disagrees with the mapped constraint - different column count or a column name at position i differs (position-sensitive comparison, same as index validation). The mapped and physical unique key must cover the same columns in the same order.","triggerScenarios":"validate with hibernate.tooling.schema.unique_key_validation=NAMED/ALL where the DB constraint covers different columns or order than @UniqueConstraint(columnNames = {...}) declares: the constraint was broadened/narrowed by a DBA; multi-tenant migrations added tenant_id to unique constraints; a column rename left the physical constraint referencing the old column.","commonSituations":"Composite unique keys evolved in the database but not in the mapping (or vice versa); tenancy refactors adding a discriminator column to uniqueness; Hibernate-version upgrades re-enabling unique-key validation against long-diverged schemas.","solutions":["Realign the constraint to the mapping: ALTER TABLE ... DROP CONSTRAINT <name>; ALTER TABLE ... ADD CONSTRAINT <name> UNIQUE (col1, col2); with exactly the mapped columns and order.","Or update @UniqueConstraint(columnNames = {...}) to match the physical definition.","If intentional divergence is required, remove the name from the mapping or set unique_key_validation=NONE for that profile."],"exampleFix":"// before: mapping says (email) but the DB constraint is (email, tenant_id)\n@Table(name = \"customer\", uniqueConstraints =\n    @UniqueConstraint(name = \"uk_customer_email\", columnNames = \"email\"))\n\n// after: match the physical constraint\n@Table(name = \"customer\", uniqueConstraints =\n    @UniqueConstraint(name = \"uk_customer_email\", columnNames = {\"email\", \"tenant_id\"}))","handlingStrategy":"validation","validationCode":"// Before validate, compare the mapped unique-key column list/order with JDBC metadata\ntry (Connection c = dataSource.getConnection();\n     ResultSet rs = c.getMetaData().getIndexInfo(null, null, \"customer\", false, true)) {\n    List<String> actual = new ArrayList<>();\n    while (rs.next()) {\n        if (\"uk_customer_email\".equalsIgnoreCase(rs.getString(\"INDEX_NAME\"))) {\n            actual.add(rs.getString(\"COLUMN_NAME\"));\n        }\n    }\n    if (!List.of(\"email\", \"tenant_id\").equals(actual)) {\n        throw new IllegalStateException(\"uk_customer_email columns mismatch: \" + actual);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    new SchemaValidator().validate(metadata, serviceRegistry);\n} catch (SchemaManagementException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Unique-key mismatch\")) {\n        // realign: rebuild the constraint with the mapped columns/order or update columnNames\n    }\n    throw e;\n}","preventionTips":["Change composite unique-key columns only via paired migration + mapping updates","Watch multi-tenant refactors that add columns to uniqueness - update both sides atomically","Run unique-key validation in CI to detect silent divergence"],"tags":["hibernate","schema-validation","unique-constraint","hbm2ddl","ddl-migration"],"backgroundTag":"unique-constraint-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}