hibernate/hibernate-orm · error · IllegalStateException
@Convert placed on @Entity/@MappedSuperclass must define att
Error message
@Convert placed on @Entity/@MappedSuperclass must define attributeName
What it means
A class-level @Convert on an @Entity, @MappedSuperclass, or @Embeddable must state which attribute it converts through attributeName, because Hibernate cannot infer the target attribute from a class placement. ClassPropertyHolder throws this IllegalStateException (note: not AnnotationException) while collecting AttributeConversionInfo when info.getAttributeName() is empty. Field-level @Convert placements do not need attributeName.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/internal/ClassPropertyHolder.java:111
return;
}
// collect superclass info first
collectAttributeConversionInfo( infoMap, entityClassDetails.getSuperClass() );
final var modelContext = getSourceModelContext();
final boolean canContainConvert =
entityClassDetails.hasAnnotationUsage( jakarta.persistence.Entity.class, modelContext )
|| entityClassDetails.hasAnnotationUsage( jakarta.persistence.MappedSuperclass.class, modelContext )
|| entityClassDetails.hasAnnotationUsage( jakarta.persistence.Embeddable.class, modelContext );
if ( ! canContainConvert ) {
return;
}
entityClassDetails.forEachAnnotationUsage( Convert.class, modelContext, (usage) -> {
final var info = new AttributeConversionInfo( usage, entityClassDetails );
if ( isEmpty( info.getAttributeName() ) ) {
throw new IllegalStateException( "@Convert placed on @Entity/@MappedSuperclass must define attributeName" );
}
infoMap.put( info.getAttributeName(), info );
} );
}
@Override
public void startingProperty(MemberDetails property) {
if ( property != null ) {
final String propertyName = property.resolveAttributeName();
if ( !attributeConversionInfoMap.containsKey( propertyName ) ) {
property.forEachAnnotationUsage( Convert.class, getSourceModelContext(), (usage) -> {
final var info = new AttributeConversionInfo( usage, property );
final String infoAttributeName = info.getAttributeName();
final String path =
isEmpty( infoAttributeName )
? propertyName
: propertyName + '.' + infoAttributeName;
attributeConversionInfoMap.put( path, info );View on GitHub (pinned to fad1729dce)
Solutions
- Add attributeName: @Convert(converter = OrderStatusConverter.class, attributeName = "status")
- Or move the @Convert annotation down onto the target field where attributeName is not needed
- For embedded sub-attributes use a dotted path in attributeName, e.g. attributeName = "address.city"
Example fix
// before
@Convert(converter = OrderStatusConverter.class) // class-level, no attributeName -> error
@Entity
public class Order {
OrderStatus status;
}
// after
@Convert(converter = OrderStatusConverter.class, attributeName = "status")
@Entity
public class Order {
OrderStatus status;
} Defensive patterns
Strategy: validation
Validate before calling
// Fail fast in a test: class-level @Convert must carry attributeName
static void checkClassLevelConverts(Class<?>... entities) {
for ( Class<?> c : entities ) {
for ( Convert convert : c.getAnnotationsByType( Convert.class ) ) {
if ( convert.attributeName().isBlank() ) {
throw new IllegalStateException( "Class-level @Convert without attributeName on "
+ c.getName() );
}
}
}
} Prevention
- Prefer field-level @Convert - it needs no attributeName
- When hoisting @Convert to class level (e.g. for embedded sub-attributes), always pair it with attributeName, including dotted paths
- Run a SessionFactory bootstrap test so converter wiring errors surface in CI
When it happens
Trigger: Writing @Convert(converter = MyConverter.class) directly on an entity/mapped-superclass/embeddable class without attributeName. The class must carry @Entity, @MappedSuperclass, or @Embeddable for the check to run at all.
Common situations: Moving @Convert from a field to the class to override a converter for an embedded sub-attribute and forgetting attributeName; applying @Converter(autoApply = true) documentation examples that omit attributeName at class level; refactoring converters during a JPA migration.
Related errors
- AttributeConverter class [%s] registered multiple times
- Unable to create AttributeConverter instance
- Error processing @TypeBinderType annotation '%s' for embedda
- Error processing @TypeBinderType annotation '%s' for entity
- error processing @AttributeBinderType annotation '%s' for at
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/fe81abc2144e4f6b.
Report an issue: GitHub.