hibernate/hibernate-orm · error · SchemaManagementException
Missing unique constraint named `%s` on table `%s`
Error message
Missing unique constraint named `%s` on table `%s`
What it means
Unique-constraint validation: the mapping declares a unique key with an explicit name, and the validator looks it up via tableInformation.getIndex(name) - Hibernate validates unique keys as indexes in JDBC metadata. If no index/constraint with that exact name exists on the table, validation fails. Only applies when hibernate.tooling.schema.unique_key_validation is NAMED (skips generated 'UK'-prefixed names) or ALL.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java:270
assert StringHelper.isNotEmpty( rawName );
assert Objects.equals( rawName, uk.getName() );
if ( validationType == ConstraintValidationType.NONE ) {
return;
}
else if ( validationType == ConstraintValidationType.NAMED ) {
if ( rawName.startsWith( "UK" ) ) {
// this is not a great check as the user could very well
// have explicitly chosen a name that starts with this as well,
// but...
return;
}
}
var name = metadata.getDatabase().toIdentifier( rawName );
final IndexInformation ukInfo = tableInformation.getIndex( name );
if ( ukInfo == null ) {
throw new SchemaManagementException(
String.format(
ROOT,
"Missing unique constraint named `%s` on table `%s`",
name.render( dialect ),
tableInformation.getName().render()
)
);
}
var matches = true;
assert uk.getColumns().size() == uk.getColumnSpan();
if ( uk.getColumnSpan() != ukInfo.getIndexedColumns().size() ) {
matches = false;
}
else {
for ( int i = 0; i < uk.getColumns().size(); i++ ) {
final Column column = uk.getColumns().get( i );
final ColumnInformation columnInfo = ukInfo.getIndexedColumns().get( i );View on GitHub (pinned to fad1729dce)
Solutions
- Recreate the constraint with the declared name: ALTER TABLE ... DROP CONSTRAINT <existing>; ALTER TABLE ... ADD CONSTRAINT uk_... UNIQUE (...);
- Or change @UniqueConstraint(name=...) to the constraint name that actually exists.
- If uniqueness is migration-managed only, drop the name (or the declaration) or set hibernate.tooling.schema.unique_key_validation=NONE.
Example fix
-- before: uniqueness exists but under a PostgreSQL-generated name (customer_email_key) ALTER TABLE customer DROP CONSTRAINT customer_email_key; -- after: constraint recreated under the name the mapping validates ALTER TABLE customer ADD CONSTRAINT uk_customer_email UNIQUE (email);
Defensive patterns
Strategy: validation
Validate before calling
// Before validate with unique_key_validation=NAMED/ALL, confirm each named constraint exists
try (Connection c = dataSource.getConnection()) {
try (ResultSet rs = c.getMetaData().getIndexInfo(null, null, "customer", false, true)) {
boolean found = false;
while (rs.next()) {
if ("uk_customer_email".equalsIgnoreCase(rs.getString("INDEX_NAME"))) found = true;
}
if (!found) {
throw new IllegalStateException("uk_customer_email missing - add it via migration before validate");
}
}
} Try / catch
try {
new SchemaValidator().validate(metadata, serviceRegistry);
} catch (SchemaManagementException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Missing unique constraint")) {
// add the constraint with the declared name or rename the @UniqueConstraint to the existing one
}
throw e;
} Prevention
- Always name @UniqueConstraint explicitly and create it with that exact name in the migration
- Avoid database-generated constraint names on schema Hibernate validates
- Enable unique_key_validation in CI once constraints and mappings are aligned
When it happens
Trigger: validate with hibernate.tooling.schema.unique_key_validation=NAMED/ALL and a named @Table(uniqueConstraints = @UniqueConstraint(name = "uk_...", columnNames = ...)), while the database enforces uniqueness under a different name: PostgreSQL auto-generated names like customer_email_key, MySQL unique keys recorded with table-prefixed names, or the constraint created by an old migration with its own naming scheme.
Common situations: Explicit constraint names added to mappings later than the schema; databases that ignore custom constraint names at creation time; legacy schemas where uniqueness is enforced by a manually created unique index rather than a named constraint.
Related errors
- Unique-key mismatch - `%s` on table `%s`
- Missing index named `%s` on table `%s`
- Index mismatch - `%s` on table `%s`
- Unrecognized 'hibernate.hbm2ddl.jdbc_metadata_extraction_str
- Schema validation: missing table [%s]
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/797141e7af9c7e4d.
Report an issue: GitHub.