hibernate/hibernate-orm · error · AnnotationException
Annotation '%s' is not assignable to '%s'
Error message
Annotation '%s' is not assignable to '%s'
What it means
castAnnotationType verifies that the attribute's type annotation is an instance of the first type argument of the AnnotationBasedUserType<A, ?> interface implemented by the custom type. A mismatched annotation triggers AnnotationException before the unsafe cast; the message names the custom type class and the interface type.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java:1200
}
@Override
public Properties getParameters() {
return parameters;
}
}
private static <A extends Annotation> A castAnnotationType(
Annotation typeAnnotation, AnnotationBasedUserType<A, ?> annotationBased ) {
final var annotationType = annotationBased.getClass();
for ( var iface: annotationType.getGenericInterfaces() ) {
if ( iface instanceof ParameterizedType parameterizedType
&& parameterizedType.getRawType() == AnnotationBasedUserType.class ) {
final var typeArguments = parameterizedType.getActualTypeArguments();
if ( typeArguments.length > 0
&& typeArguments[0] instanceof Class<?> annotationClass ) {
if ( !annotationClass.isInstance( typeAnnotation ) ) {
throw new AnnotationException( String.format( "Annotation '%s' is not assignable to '%s'",
annotationType.getName(), iface.getTypeName() ) );
}
@SuppressWarnings("unchecked") // safe, we just checked it
final var castAnnotation = (A) typeAnnotation;
return castAnnotation;
}
}
}
throw new AssertionFailure( "Could not find implementing interface" );
}
private <T extends UserType<?>, A extends Annotation> T instantiateUserType(
Class<T> customType, A typeAnnotation,
UserTypeCreationContext creationContext) {
try {
T userType;
if ( typeAnnotation != null ) {
@SuppressWarnings("unchecked") // totally safeView on GitHub (pinned to fad1729dce)
Solutions
- Put the exact annotation matching the generic parameter on the attribute.
- Update the custom type's AnnotationBasedUserType<A, ...> parameter to the annotation actually used.
- Remove stray type annotations from the attribute so the right one is selected.
Example fix
// before @OtherFormat @CustomType(MyFormatType.class) // implements AnnotationBasedUserType<MyFormat, ?> private String value; // after @MyFormat(style = "short") @CustomType(MyFormatType.class) private String value;
Defensive patterns
Strategy: validation
Validate before calling
static boolean annotationMatches( Class<? extends Annotation> found,
Class<? extends AnnotationBasedUserType<?, ?>> userType ) {
for ( var iface : userType.getGenericInterfaces() ) {
if ( iface instanceof ParameterizedType pt
&& pt.getRawType() == AnnotationBasedUserType.class
&& pt.getActualTypeArguments()[0] instanceof Class<?> expected ) {
return expected.isAssignableFrom( found );
}
}
return false;
} Prevention
- Keep the custom type and its annotation in the same package and change them together
- Apply only one type annotation per attribute
- Unit-test the pairing of custom types with their annotations at bootstrap
When it happens
Trigger: Custom type implements AnnotationBasedUserType<MyAnn, ?> but the attribute carries a different custom annotation (@OtherAnn); multiple type annotations present where the wrong one is picked; refactoring the generic parameter without updating mappings.
Common situations: Renamed or repackaged annotation classes; two similar annotation-based types applied together; copy-paste of @CustomType without the matching annotation.
Related errors
- Wrong kind of binder for annotation type: '%s' does not acce
- Custom type '%s' implements 'AnnotationBasedUserType' but no
- Class '<componentClassName>' is an '@Embeddable' type and ma
- Property '<propertyName>' may not be annotated '@BatchSize'
- One to many association '<propertyName>' was annotated '@Col
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/d90c5a0fc59ea499.
Report an issue: GitHub.