hibernate/hibernate-orm · error · AnnotationException
Custom type '%s' implements 'AnnotationBasedUserType' but no
Error message
Custom type '%s' implements 'AnnotationBasedUserType' but no custom type annotation is present
What it means
UserTypes implementing AnnotationBasedUserType<A, ?> are initialized with the type annotation found on the mapped attribute. When no such annotation is present (typeAnnotation == null), Hibernate throws AnnotationException naming the custom type class, since initialize(...) cannot run without configuration.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java:1155
initializeAnnotationBasedUserType( typeAnnotation, annotationBased, creationContext );
}
return typeInstance;
}
private void addParameterType(Properties properties, UserType<?> typeInstance) {
if ( typeInstance instanceof DynamicParameterizedType
&& parseBoolean( properties.getProperty( DynamicParameterizedType.IS_DYNAMIC ) )
&& properties.get( DynamicParameterizedType.PARAMETER_TYPE ) == null ) {
properties.put( DynamicParameterizedType.PARAMETER_TYPE, createParameterType() );
}
}
private <A extends Annotation> void initializeAnnotationBasedUserType(
Annotation typeAnnotation,
AnnotationBasedUserType<A, ?> annotationBased,
UserTypeCreationContext creationContext) {
if ( typeAnnotation == null ) {
throw new AnnotationException( String.format(
"Custom type '%s' implements 'AnnotationBasedUserType' but no custom type annotation is present",
annotationBased.getClass().getName() ) );
}
annotationBased.initialize( castAnnotationType( typeAnnotation, annotationBased ), creationContext );
}
private class TypeCreationContext implements UserTypeCreationContext {
private final Properties parameters;
private TypeCreationContext(Properties parameters) {
this.parameters = parameters;
}
@Override
public MetadataBuildingContext getBuildingContext() {
return BasicValue.this.getBuildingContext();
}
View on GitHub (pinned to fad1729dce)
Solutions
- Annotate the attribute with the annotation the custom type declares (e.g., @MyAnn with its parameters).
- If the type needs no annotation configuration, drop AnnotationBasedUserType from its interfaces.
- When applying types centrally, also transfer the expected annotation onto each attribute.
Example fix
// before: type implements AnnotationBasedUserType<Formatted, ?> @CustomType(FormattedStringType.class) private String note; // after @Formatted(uppercase = true) @CustomType(FormattedStringType.class) private String note;
Defensive patterns
Strategy: validation
Validate before calling
static boolean annotationPresent( Field f, Class<? extends Annotation> expected ) {
return f.isAnnotationPresent( expected );
}
// for each @CustomType attribute, assert the annotation declared by its AnnotationBasedUserType is present Prevention
- Pair every annotation-based custom type with its annotation in one shared meta-annotation
- Do not apply AnnotationBasedUserType implementations via plain @Type/@TypeDef
- Add an architecture test that checks @CustomType attributes carry their expected annotation
When it happens
Trigger: @CustomType(MyType.class) where MyType implements AnnotationBasedUserType<MyAnn, ?> but the attribute carries no @MyAnn; registering such a type via plain @Type/@TypeDef so the annotation never reaches it; attribute carrying only unrelated annotations.
Common situations: Adopting Hibernate 6.2+ annotation-based custom types incrementally; frameworks applying custom types centrally without the paired annotation; copying a custom type declaration without its annotation.
Related errors
- Annotation '%s' is not assignable to '%s'
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
- Collection '<propertyName>' was annotated '@Collate'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/876f86e02d9077ba.
Report an issue: GitHub.