hibernate/hibernate-orm · error · MappingException
collection id mapping has wrong number of columns: " + getRo
Error message
collection id mapping has wrong number of columns: " + getRole() + " type: " + getIdentifier().getType().getName()
What it means
IdentifierCollection#validate checks the surrogate id mapping of an idbag collection (<idbag> / @CollectionId) and throws when the id Value is not valid - in practice its column span does not match the declared type, for example a multi-column type used as the collection id.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/mapping/IdentifierCollection.java:79
&& isSame( identifier, other.identifier );
}
void createPrimaryKey() {
if ( !isOneToMany() ) {
final var primaryKey = new PrimaryKey( getCollectionTable() );
primaryKey.addColumns( getIdentifier() );
getCollectionTable().setPrimaryKey( primaryKey );
}
// create an index on the key columns??
}
public void validate(MappingContext mappingContext) throws MappingException {
super.validate( mappingContext );
assert getElement() != null : "IdentifierCollection identifier not bound : " + getRole();
if ( !getIdentifier().isValid( mappingContext ) ) {
throw new MappingException(
"collection id mapping has wrong number of columns: " +
getRole() +
" type: " +
getIdentifier().getType().getName()
);
}
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Give the collection id a single-column basic type (long, or UUID stored as one column) with an explicit @Column.
- Declare the generator explicitly on @CollectionId (e.g. a sequence generator) so the id resolves cleanly.
- Where possible replace legacy idbags with a normal @ElementCollection plus @OrderColumn, or promote the bag to an owning entity row.
Example fix
// before - multi-column type as collection id
@CollectionId(
columns = @Column(name = "bag_id"),
type = @Type(StringArrayType.class),
generator = "seq"
)
Collection<String> tags;
// after - single-column basic type
@CollectionId(
columns = @Column(name = "bag_id"),
type = @Type(LongType.class),
generator = "seq"
)
Collection<String> tags; Defensive patterns
Strategy: try-catch
Try / catch
try {
metadata = sources.buildMetadata();
} catch (MappingException e) {
// message contains the collection role + id type name - inspect the
// @CollectionId / <collection-id> of that role
throw e;
} Prevention
- Prefer @ElementCollection with @OrderColumn over legacy @CollectionId/idbag for new mappings.
- Always specify columns, type, and generator explicitly on @CollectionId.
- Cover every collection mapping with a Metadata-building unit test.
When it happens
Trigger: A @CollectionId whose type maps to more than one column; an hbm <collection-id> whose type/column combination does not resolve; forgetting the @Column for the collection id; using an array or composite type as the bag id.
Common situations: Legacy idbag mappings migrated between Hibernate versions; introducing custom types into @CollectionId; hand-editing hbm <idbag> elements.
Related errors
- @TargetEmbeddable can only be specified on properties marked
- Expecting column for collection id (idbag), but found formul
- collection index mapping has wrong number of columns: " + ge
- Basic collection has element type '%s' which is not a known
- Unsupported attempt to resolve JDBC type for Map.Entry
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/1d2a1ffbf2aeee93.
Report an issue: GitHub.