hibernate/hibernate-orm · error · MappingException

Non-terminal property path did not reference FetchableContai

Error message

Non-terminal property path did not reference FetchableContainer - %s 

What it means

When a return-property path is resolved against the runtime metamodel, Hibernate walks it part by part: after the first part it requires the current Fetchable to also be a FetchableContainer (an embeddable, association, or collection) before descending to the next part. If an intermediate part resolves to a basic-valued attribute, there is nothing to descend into and this MappingException is thrown with the NavigablePath reached so far.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/query/HbmResultSetMappingDescriptor.java:659

		@Override
		public FetchMemento resolve(@Nonnull ResultSetMappingResolutionContext resolutionContext) {
			BootQueryLogging.BOOT_QUERY_LOGGER.tracef(
					"Resolving HBM PropertyFetchDescriptor into memento - %s : %s",
					parent,
					propertyPath
			);

			final FetchParentMemento fetchParentMemento = parent.resolveParentMemento( resolutionContext );

			Fetchable fetchable = (Fetchable) fetchParentMemento.getFetchableContainer().findSubPart(
					propertyPathParts[ 0 ],
					null
			);
			NavigablePath navigablePath = fetchParentMemento.getNavigablePath().append( fetchable.getFetchableName() );

			for ( int i = 1; i < propertyPathParts.length; i++ ) {
				if ( ! ( fetchable instanceof FetchableContainer ) ) {
					throw new MappingException(
							String.format(
									Locale.ROOT,
									"Non-terminal property path did not reference FetchableContainer - %s ",
									navigablePath
							)
					);
				}
				fetchable = (Fetchable) ( (FetchableContainer) fetchable.getPartMappingType() ).findSubPart( propertyPathParts[i], null );
				navigablePath = navigablePath.append( fetchable.getFetchableName() );
			}

			final BasicValuedModelPart basicPart = fetchable.asBasicValuedModelPart();
			if ( basicPart != null ) {
				return new FetchMementoBasicStandard(
						navigablePath,
						basicPart,
						columnAliases.get( 0 )
				);

View on GitHub (pinned to fad1729dce)

Solutions

  1. Shorten the path so it ends at the basic attribute: 'address.zip'.
  2. If the target really is nested, make the intermediate segment a true embeddable (@Embeddable/<component>) so it is a FetchableContainer.
  3. Re-check the property structure of the entity with the metamodel or the mapping document and align the path to it.

Example fix

<!-- before: 'address.zip' is a basic String, cannot descend to '.code' -->
<return-property name="address.zip.code" column="ZIP"/>

<!-- after -->
<return-property name="address.zip" column="ZIP"/>
Defensive patterns

Strategy: validation

Validate before calling

// pre-check a dotted return-property path: every non-final segment must be an embeddable/association
SqmPathSource<?> current = (SqmPathSource<?>) entityType.getAttributes().stream()
        .filter( a -> a.getName().equals( parts[0] ) ).findFirst().orElseThrow();
for ( int i = 1; i < parts.length - 1; i++ ) {
    if ( ! ( current.getSqmPathType() instanceof EmbeddableTypeImpl || current.isAssociation() ) ) {
        throw new IllegalStateException( "Segment '" + parts[i-1] + "' is basic; cannot descend to " + propertyPath );
    }
    current = (SqmPathSource<?>) ( (ManagedDomainType<?>) current.getSqmPathType() ).getAttribute( parts[i] );
}

Try / catch

catch ( MappingException e ) {
    if ( e.getMessage().startsWith( "Non-terminal property path" ) ) {
        // trim the path to the last basic attribute, or model the intermediate as an embeddable
    }
}

Prevention

When it happens

Trigger: A return-property name like 'address.zip.code' where 'address.zip' is a plain String; a path that keeps appending segments after a terminal basic attribute; treating a basic column as if it were an embedded component.

Common situations: An embeddable was flattened into basic columns during refactoring while the native query mapping kept the long dotted path; porting mappings between entities whose component structure differs.

Related errors


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