hibernate/hibernate-orm · error · SchemaManagementException
Schema validation: missing table [%s]
Error message
Schema validation: missing table [%s]
What it means
Schema validation (hibernate.hbm2ddl.auto=validate, or SchemaValidator) compared each mapped entity table against live JDBC metadata and found no table under the entity's qualified name (tableInformation == null in validateTable). Validation is read-only and never creates anything, so any mapped table missing from the database aborts SessionFactory bootstrap with this error.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java:127
}
}
}
protected abstract void validateTables(
Metadata metadata,
DatabaseInformation databaseInformation,
ExecutionOptions options,
ContributableMatcher contributableInclusionFilter,
Dialect dialect, Namespace namespace);
protected void validateTable(
Table table,
TableInformation tableInformation,
Metadata metadata,
ExecutionOptions options,
Dialect dialect) {
if ( tableInformation == null ) {
throw new SchemaManagementException(
String.format(
"Schema validation: missing table [%s]",
table.getQualifiedTableName().toString()
)
);
}
for ( var column : table.getColumns() ) {
final var existingColumn =
//QUESTION: should this use metadata.getDatabase().toIdentifier( column.getQuotedName() )
tableInformation.getColumn( toIdentifier( column.getQuotedName() ) );
if ( existingColumn == null ) {
throw new SchemaManagementException(
String.format(
"Schema validation: missing column [%s] in table [%s]",
column.getName(),
table.getQualifiedTableName()
)View on GitHub (pinned to fad1729dce)
Solutions
- Run the schema migrations (or SchemaExport create) in that environment before startup with validate.
- Verify the connection URL, catalog, and hibernate.default_schema/default_catalog resolve the schema that actually holds the table.
- Align the mapped name with the physical table: fix @Table(name=...) or use a consistent PhysicalNamingStrategy.
- If the table is intentionally absent (e.g. optional module), exclude the entities from the validated metadata or drop validate for that profile.
Example fix
// before: entity expects ORDERS but PostgreSQL created orders (unquoted names are folded)
@Entity
@Table(name = "ORDERS")
public class Order { ... }
// after: match the physical name
@Entity
@Table(name = "orders")
public class Order { ... } Defensive patterns
Strategy: validation
Validate before calling
// Before booting with hbm2ddl.auto=validate, verify every mapped table exists via JDBC metadata
try (Connection c = dataSource.getConnection()) {
for (String table : List.of("orders", "customers", "order_lines")) {
try (ResultSet rs = c.getMetaData().getTables(null, null, table, new String[]{"TABLE"})) {
if (!rs.next()) {
throw new IllegalStateException("Migrations incomplete: table " + table + " missing - refusing to validate");
}
}
}
} Try / catch
try {
sessionFactory = metadata.buildSessionFactory(); // with hbm2ddl.auto=validate
} catch (SchemaManagementException e) {
if (e.getMessage() != null && e.getMessage().contains("missing table")) {
// mapping/database drift: report the qualified name, run migrations or fix naming, then retry bootstrap once
}
throw e;
} Prevention
- Always run migrations before validate; wire Flyway/Liquibase to execute before Hibernate initializes
- Pin hibernate.default_schema/default_catalog explicitly instead of relying on connection defaults
- Run a CI step that boots the app with validate against a freshly migrated schema
- Never change the PhysicalNamingStrategy without regenerating/reviewing schema names
When it happens
Trigger: SessionFactory startup with hbm2ddl.auto=validate when the extractor cannot find table.getQualifiedTableName(): the schema was never created or migrations were not run in that environment; the JDBC URL/default_schema resolves a different namespace; the physical naming strategy or @Table name produces a name that differs from the physical table (case folding on PostgreSQL, quoted vs unquoted identifiers).
Common situations: Deploying with ddl-auto=validate before Flyway/Liquibase has run; pointing at the wrong database/schema in the connection URL; changing the PhysicalNamingStrategy between releases; validating against a replica or role that cannot see the app schema; Postgres lowercasing unquoted CamelCase names at creation time while the mapping now expects CamelCase.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Schema validation: missing column [%s] in table [%s]
- Unrecognized 'hibernate.hbm2ddl.jdbc_metadata_extraction_str
- Export identifier [%s] encountered more than once
- Schema validation: wrong column type encountered in column [
- Missing index named `%s` on table `%s`
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/b687f5568a084a76.
Report an issue: GitHub.