hibernate/hibernate-orm · error · IllegalArgumentException
Tried to resolve the JdbcType [%s] as AggregateJdbcType but
Error message
Tried to resolve the JdbcType [%s] as AggregateJdbcType but it does not implement that interface!
What it means
During boot, JdbcTypeRegistry.resolveAggregateDescriptor looks up the JdbcType registered for the requested JDBC type code and requires it to implement AggregateJdbcType when an embeddable is mapped onto an aggregate column. If a non-aggregate descriptor is registered under that code, aggregate mapping creation fails with this IllegalArgumentException naming the offending class.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/spi/JdbcTypeRegistry.java:185
}
return resolveAggregateDescriptor( jdbcTypeCode, typeName, embeddableMappingType, context, registrationKey );
}
private AggregateJdbcType resolveAggregateDescriptor(
int jdbcTypeCode,
String typeName,
EmbeddableMappingType embeddableMappingType,
RuntimeModelCreationContext context,
String registrationKey) {
final var descriptor = getDescriptor( jdbcTypeCode );
if ( descriptor instanceof AggregateJdbcType aggregateJdbcType ) {
final AggregateJdbcType resolvedJdbcType =
aggregateJdbcType.resolveAggregateJdbcType( embeddableMappingType, typeName, context );
cacheAggregateJdbcType( registrationKey, resolvedJdbcType );
return resolvedJdbcType;
}
else {
throw new IllegalArgumentException(
String.format(
"Tried to resolve the JdbcType [%s] as AggregateJdbcType but it does not implement that interface!",
descriptor.getClass().getName()
)
);
}
}
private void cacheAggregateJdbcType(String registrationKey, AggregateJdbcType resolvedJdbcType) {
if ( registrationKey != null ) {
aggregateDescriptorMap.put( registrationKey, resolvedJdbcType );
if ( resolvedJdbcType instanceof SqlTypedJdbcType sqlTypedJdbcType ) {
sqlTypedDescriptorMap.put(
sqlTypedJdbcType.getSqlTypeName().toLowerCase( Locale.ROOT ),
sqlTypedJdbcType
);
}
}View on GitHub (pinned to fad1729dce)
Solutions
- Use the intended aggregate annotation: @Struct, or @JdbcTypeCode(SqlTypes.STRUCT | SqlTypes.JSON | SqlTypes.SQLXML) on the embeddable.
- If a custom JdbcType must back the aggregate, make it implement AggregateJdbcType (extend or delegate to XmlJdbcType/JsonJdbcType/StructJdbcType).
- Find and remove/fix the JdbcTypeRegistrar or TypeContributor that overrode the code, e.g. by enabling Hibernate's type logging at startup.
Example fix
// before: non-aggregate type forced onto an aggregate mapping
@Embeddable
@JdbcType(VarcharJdbcType.class) // -> Tried to resolve the JdbcType ... as AggregateJdbcType
public class Details { ... }
// after
@Embeddable
@JdbcTypeCode(SqlTypes.JSON) // registered descriptor implements AggregateJdbcType
public class Details { ... } Defensive patterns
Strategy: validation
Validate before calling
static void assertAggregateCapable(JdbcType jdbcType) {
if (!(jdbcType instanceof AggregateJdbcType)) {
throw new IllegalStateException(jdbcType.getClass().getName()
+ " must implement AggregateJdbcType to back an aggregate mapping");
}
} Type guard
static boolean isAggregateJdbcType(JdbcType t) {
return t instanceof AggregateJdbcType;
} Try / catch
try {
sessionFactory = new Configuration().addAnnotatedClass(Person.class)
.buildSessionFactory();
} catch (IllegalArgumentException ex) {
if (ex.getMessage() != null && ex.getMessage().contains("as AggregateJdbcType")) {
throw new ConfigurationException(
"An embeddable aggregate resolves to a non-aggregate JdbcType; "
+ "check @JdbcType/@JdbcTypeCode and custom JdbcTypeRegistrars", ex);
}
throw ex;
} Prevention
- Use @Struct or @JdbcTypeCode(SqlTypes.STRUCT/JSON/SQLXML) on aggregate-mapped embeddables.
- Make custom JdbcTypes for aggregate columns implement AggregateJdbcType by extending XmlJdbcType/JsonJdbcType/StructJdbcType.
- Audit classpath type contributors (JdbcTypeRegistrar, TypeContributor) after dependency upgrades.
When it happens
Trigger: Mapping an embeddable as an aggregate while the effective JdbcType for the column is not aggregate-capable: @JdbcType on the embeddable pointing at a plain JdbcType, @JdbcTypeCode with a code whose registered descriptor is not aggregate (e.g. SqlTypes.VARCHAR on an embeddable), or a custom JdbcTypeRegistrar/TypeContributor overriding SqlTypes.STRUCT/JSON/SQLXML codes with a non-aggregate implementation.
Common situations: Custom type contributions added by a library or dialect integration; copy-pasted @JdbcType annotations from non-aggregate mappings; conflicting type contributors on the classpath after dependency upgrades.
Related errors
- Identifier property '" + getPath( holder, data ) + "' cannot
- Class or package level '@NamedQuery' annotation must specify
- Class or package level '@NamedStatement' annotation must spe
- Class or package level '@NamedNativeQuery' annotation must s
- Class or package level '@NamedStoredProcedureQuery' annotati
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/67b37af8d57acbe5.
Report an issue: GitHub.