hibernate/hibernate-orm · error · SchemaManagementException

Schema validation: missing column

Error message

Schema validation: missing column [%s] in table [%s]

What it means

Schema validation found the table but one of the columns the entity maps is absent from the live table: tableInformation.getColumn(toIdentifier(column.getQuotedName())) returned null for a mapped column. This is column-level drift between the entity model and the physical schema; validation is read-only so it aborts bootstrap instead of altering anything.

Solutions

  1. Write the migration that adds the column (ALTER TABLE ... ADD COLUMN ...) or revert the entity change until a migration ships.
  2. Align @Column(name=...) with the physical column, including case/quoting on case-sensitive databases.
  3. Confirm the physical naming strategy produces exactly the physical name (log or assert generated names in a test).
  4. If the column genuinely should not exist, remove it from the mapping.

Example fix

// before: mapping expects display_name, but the physical column is name_label
@Column(name = "display_name")
private String displayName;

// after: either match the physical column ...
@Column(name = "name_label")
private String displayName;

// ... or migrate the schema
// ALTER TABLE customer ADD COLUMN display_name varchar(255);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check critical columns before validate
try (Connection c = dataSource.getConnection()) {
    DatabaseMetaData md = c.getMetaData();
    try (ResultSet rs = md.getColumns(null, null, "customer", "display_name")) {
        if (!rs.next()) {
            throw new IllegalStateException("customer.display_name missing - run pending migrations before validate");
        }
    }
}

Try / catch

try {
    sessionFactory = metadata.buildSessionFactory(); // hbm2ddl.auto=validate
} catch (SchemaManagementException e) {
    if (e.getMessage() != null && e.getMessage().contains("missing column")) {
        // parse column + table from the message, add the migration or fix @Column name/quoting, retry
    }
    throw e;
}

Prevention

When it happens

Trigger: hibernate.hbm2ddl.auto=validate where the table exists but lacks a mapped column: a new entity field was added without a migration; @Column(name=...) does not match the physical column (naming strategy snake_case vs camelCase vs explicit name); the column was dropped or renamed manually; the entity maps a database view that is missing the attribute; case/quoting differences on case-sensitive databases.

Common situations: Adding fields on a feature branch and validating against an old schema; Spring Boot's CamelCase-to-snake strategy interacting with explicit @Column names; a DBA renamed columns; Oracle upper-case columns vs lowercase mappings; H2 test schema drifting from production Postgres.

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


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

Appendix: source

Thrown at hibernate-core/src/main/java/org/hibernate/tool/schema/internal/AbstractSchemaValidator.java:140

			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()
						)
				);
			}
			validateColumnType( table, column, existingColumn, metadata, dialect );
		}

		validateIndexes( table, tableInformation, metadata, options, dialect );
		validateUniqueKeys( table, tableInformation, metadata, options, dialect );
	}

	protected void validateColumnType(
			Table table,
			Column column,
			ColumnInformation columnInformation,

View on GitHub (pinned to fad1729dce)