hibernate/hibernate-orm · error · IllegalArgumentException
Named type [${typeImplementorClass}] did not implement Basic
Error message
Named type [${typeImplementorClass}] did not implement BasicType nor UserType What it means
When a named type (from hbm.xml <typedef>/<type name=.../>) resolves to a class that is not a BasicType/UserType implementation, TypeDefinition falls back to 'legacy' adaptation: Serializable classes become SerializableType, interfaces become JavaObjectType, and everything else throws IllegalArgumentException('Named type [X] did not implement BasicType nor UserType'). Plain non-serializable classes cannot be adapted into a Hibernate basic type.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/model/TypeDefinition.java:246
// Series of backward compatible special cases
return resolveLegacyCases( typeImplementorClass, indicators, typeConfiguration );
}
private static <T> BasicValue.Resolution<T> resolveLegacyCases(
Class<T> typeImplementorClass, JdbcTypeIndicators indicators, TypeConfiguration typeConfiguration) {
return createBasicTypeResolution( getLegacyType( typeImplementorClass ),
typeImplementorClass, indicators, typeConfiguration );
}
private static <T> BasicType<T> getLegacyType(Class<T> typeImplementorClass) {
if ( Serializable.class.isAssignableFrom( typeImplementorClass ) ) {
return new SerializableType( typeImplementorClass );
}
else if ( typeImplementorClass.isInterface() ) {
return (BasicType<T>) new JavaObjectType();
}
else {
throw new IllegalArgumentException( "Named type [" + typeImplementorClass
+ "] did not implement BasicType nor UserType" );
}
}
private static <T> BasicValue.Resolution<T> createBasicTypeResolution(
BasicType<T> type,
Class<T> typeImplementorClass,
JdbcTypeIndicators indicators,
TypeConfiguration typeConfiguration) {
final var jtd = typeConfiguration.getJavaTypeRegistry().resolveDescriptor( typeImplementorClass );
final var jdbcType = typeConfiguration.getJdbcTypeRegistry().getDescriptor( Types.VARBINARY );
final var basicType = typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType );
final var resolved = resolveSqlTypeIndicators( indicators, basicType, jtd );
return new BasicValue.Resolution<>() {
@Override
public JdbcMapping getJdbcMapping() {
return resolved;View on GitHub (pinned to fad1729dce)
Solutions
- Write a custom type implementing org.hibernate.usertype.UserType (or CompositeUserType) for the value class and reference that type's class name in the mapping
- Alternatively make the value class implement java.io.Serializable so the legacy SerializableType adaptation applies (stores as serialized binary — usually the worse option)
- Verify the FQN in the mapping is the type class, not the domain value class, and that it exists on the classpath
Example fix
<!-- before --> <typedef name="money" class="com.acme.Money"/> <!-- plain value class --> <!-- after --> <typedef name="money" class="com.acme.MoneyType"/> <!-- implements UserType -->
Defensive patterns
Strategy: type-guard
Type guard
static boolean isAdaptableAsHibernateType(Class<?> c) {
return org.hibernate.type.BasicType.class.isAssignableFrom(c)
|| org.hibernate.usertype.UserType.class.isAssignableFrom(c)
|| org.hibernate.usertype.CompositeUserType.class.isAssignableFrom(c)
|| java.io.Serializable.class.isAssignableFrom(c)
|| c.isInterface();
} Try / catch
catch (IllegalArgumentException e) {
if (String.valueOf(e.getMessage()).contains("did not implement BasicType nor UserType")) {
throw new IllegalStateException("Referenced type class must implement UserType/BasicType - fix the typedef class", e);
}
throw e;
} Prevention
- Reference custom UserType implementations in <typedef class=...>, never the value class
- Add a unit test that resolves every configured typedef at startup
When it happens
Trigger: A <typedef class="com.acme.Money"/> or @Type(...)/hbm <type name="..."> pointing at a class that implements none of Hibernate's type interfaces and is neither Serializable nor an interface — most often the value class itself instead of a UserType that wraps it, or a typo that resolves to some other plain class.
Common situations: Mapping a custom value object directly by class name instead of writing a UserType; classpaths where the intended UserType class was renamed so the FQN now hits an unrelated class; legacy hbm.xml brought forward from very old Hibernate versions.
Related errors
- No support for parsing UserType values from String: {}
- Unable to determine SQL type name for column '%s' of table '
- Class '" + typeName + "' does not implement '" + supertype.g
- Expecting Component for id mapping with no id-attribute
- No support for parsing UserType values from String: {}
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/ef4b5d02d88d4c51.
Report an issue: GitHub.