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

  1. Use the intended aggregate annotation: @Struct, or @JdbcTypeCode(SqlTypes.STRUCT | SqlTypes.JSON | SqlTypes.SQLXML) on the embeddable.
  2. If a custom JdbcType must back the aggregate, make it implement AggregateJdbcType (extend or delegate to XmlJdbcType/JsonJdbcType/StructJdbcType).
  3. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/67b37af8d57acbe5. Report an issue: GitHub.