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

  1. Recreate the constraint with the declared name: ALTER TABLE ... DROP CONSTRAINT <existing>; ALTER TABLE ... ADD CONSTRAINT uk_... UNIQUE (...);
  2. Or change @UniqueConstraint(name=...) to the constraint name that actually exists.
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/797141e7af9c7e4d. Report an issue: GitHub.