hibernate/hibernate-orm · error · IllegalArgumentException

Couldn't determine basic type for java type: {}

Error message

Couldn't determine basic type for java type: {}

What it means

While building the path source for a navigable function result, SqmFunctionPath.determinePathSource looks up the function's return Java type in the JpaMetamodel (managed types) and then in the basic-type registry. If neither knows the Java type, no SqmPathSource can be constructed and IllegalArgumentException is thrown naming the class. This means the function returns a Java type for which no basic/mapped type is registered.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmFunctionPath.java:64

		this.function = function;
	}

	private static <X> SqmPathSource<X> determinePathSource(NavigablePath navigablePath, SqmFunction<?> function) {
		//noinspection unchecked
		final var nodeType = (SqmBindableType<X>) function.getNodeType();
		if ( nodeType == null ) {
			throw new IllegalArgumentException( "Null return type for function: " + function.getFunctionName() );
		}
		final var bindableJavaType = nodeType.getJavaType();
		final var managedType =
				function.nodeBuilder().getJpaMetamodel()
						.findManagedType( bindableJavaType );
		if ( managedType == null ) {
			final var basicType =
					function.nodeBuilder().getTypeConfiguration()
							.getBasicTypeForJavaType( bindableJavaType );
			if ( basicType == null ) {
				throw new IllegalArgumentException( "Couldn't determine basic type for java type: " + bindableJavaType.getName() );
			}
			return new BasicSqmPathSource<>(
					navigablePath.getFullPath(),
					null,
					basicType,
					basicType.getRelationalJavaType(),
					Bindable.BindableType.SINGULAR_ATTRIBUTE,
					false
			);
		}
		else if ( managedType.getPersistenceType() == Type.PersistenceType.EMBEDDABLE ) {
			return new EmbeddedSqmPathSource<>(
					navigablePath.getFullPath(),
					null,
					(SqmEmbeddableDomainType<X>) managedType,
					Bindable.BindableType.SINGULAR_ATTRIBUTE,
					false
			);

View on GitHub (pinned to fad1729dce)

Solutions

  1. Register a basic type / JavaTypeDescriptor for the return Java type (metadataBuilder.applyBasicType(...), @JavaTypeRegistration, or a TypeContributor) so getBasicTypeForJavaType(rt) resolves
  2. Change the function descriptor to declare a standard mapped return type (String, Integer, etc.)
  3. Wrap the call in cast(f(x) as ...) to force a concrete mapped type before navigating
  4. If the return type is actually a mapped embeddable/entity, make sure it is part of the persistence unit so findManagedType finds it

Example fix

// before: function returns Money, no type registered
// HQL: select money_of(p).amount from Person p
//  -> "Couldn't determine basic type for java type: com.acme.Money"

// after: register the type before building the SessionFactory
StandardServiceRegistryBuilder builder = ...;
MetadataBuilder mb = new MetadataBuilderImpl(builder.build())...;
mb.applyBasicType(new MoneyType()); // Money <-> MoneyType mapping
// or annotate the domain class: @JavaType(MoneyJavaTypeDescriptor.class)
Defensive patterns

Strategy: validation

Validate before calling

// verify the function's return Java type is known to the factory before navigating
Class<?> rt = function.getNodeType().getJavaType();
SessionFactoryImplementor sfi = emf.unwrap(SessionFactoryImplementor.class);
boolean known = sfi.getJpaMetamodel().findManagedType(rt) != null
            || sfi.getTypeConfiguration().getBasicTypeForJavaType(rt) != null;
if (!known) {
    throw new IllegalStateException("No basic/managed type registered for " + rt.getName()
        + "; register it via metadataBuilder.applyBasicType or @JavaTypeRegistration");
}

Try / catch

try {
    path = new SqmFunctionPath<>(function).get(attr);
} catch (IllegalArgumentException e) {
    // message names the unmapped Java type: add a BasicType/JavaTypeDescriptor registration
    throw new IllegalStateException("Unmapped function return type; register a type mapping", e);
}

Prevention

When it happens

Trigger: A custom function whose descriptor declares an exotic return Java type (custom value class, Object, Serializable, an unregistered record) with no BasicType/JavaTypeDescriptor registered; navigating attributes from such a function result: f(e.x).sub.

Common situations: Domain value objects (Money, Coordinate) used as function return types without a @Type/JavaTypeRegistration or BasicTypeContributor; upgrading Hibernate versions where lax type resolution was tightened; functions returning Object in utility libraries.

Related errors


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