hibernate/hibernate-orm · error · UnknownPathException
Could not interpret attribute '%s' of basic-valued path '%s'
Error message
Could not interpret attribute '%s' of basic-valued path '%s'
What it means
Hibernate throws UnknownPathException from SqmBasicValuedSimplePath.resolvePathPart when HQL/JPQL path navigation tries to continue past an attribute that is a basic type (String, Integer, enum, converted object). A basic value has no sub-attributes, so the SQM semantic analyzer cannot resolve the requested attribute name on the path. The offending path part and the full navigable path are included in the message. The query fails at interpretation time, before any SQL is generated.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmBasicValuedSimplePath.java:109
@Override
public @Nonnull SqmBindableType<T> getExpressible() {
return this;
}
@Override
public PersistenceType getPersistenceType() {
return BASIC;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SemanticPathPart
@Override
public SqmPath<?> resolvePathPart(
String name,
boolean isTerminal,
SqmCreationState creationState) {
throw new UnknownPathException(
String.format(
"Could not interpret attribute '%s' of basic-valued path '%s'",
name, getNavigablePath()
)
);
}
@Override
public SqmPath<?> resolveIndexedAccess(
SqmExpression<?> selector,
boolean isTerminal,
SqmCreationState creationState) {
final var pathRegistry =
creationState.getCurrentProcessingState().getPathRegistry();
final String alias = selector.toHqlString();
final NavigablePath navigablePath =
getParentNavigablePath().append( CollectionPart.Nature.ELEMENT.getName(), alias );
final SqmFrom<?, ?> indexedPath = pathRegistry.findFromByPath( navigablePath );View on GitHub (pinned to fad1729dce)
Solutions
- Remove or correct the trailing path segment so navigation stops at the basic attribute (use e.firstName, not e.name.firstName).
- If the attribute is genuinely a structured object, map it as @Embeddable/@Embedded (or as an @OneToOne association) instead of a basic type with an AttributeConverter, then navigation will resolve.
- If you wanted a String operation, use an HQL function (length(e.name), lower(e.name), substring(...)) instead of dot-path syntax.
- Verify every path segment against the JPA metamodel or the entity class to catch typos before running the query.
Example fix
// before - throws UnknownPathException if e.name is a basic String
List<String> names = session.createQuery("select e.name.first from Employee e", String.class).list();
// after - navigate only while the type is embeddable/entity, stop at basic values
List<String> names = session.createQuery("select e.name from Employee e", String.class).list(); Defensive patterns
Strategy: validation
Validate before calling
// Walk each path segment against the JPA metamodel before running the query
static void assertNavigable(ManagedType<?> type, String... segments) {
for (int i = 0; i < segments.length; i++) {
Attribute<?, ?> attr = type.getAttribute(segments[i]);
if (i == segments.length - 1) return; // last segment: fine
if (!(attr instanceof SingularAttribute<?, ?> singular)
|| !(singular.getType() instanceof ManagedType<?>)) {
throw new IllegalArgumentException(
"Segment '" + segments[i] + "' is basic; cannot navigate to '" + segments[i + 1] + "'");
}
type = (ManagedType<?>) singular.getType();
}
} Type guard
static boolean isBasicValued(ManagedType<?> owner, String attrName) {
Attribute<?, ?> a = owner.getAttribute(attrName);
return !(a instanceof SingularAttribute<?, ?> s) || !(s.getType() instanceof ManagedType<?>);
} Try / catch
try {
return session.createQuery(hql, type).list();
} catch (org.hibernate.query.UnknownPathException e) {
throw new IllegalArgumentException("Invalid path in query: " + hql + " - " + e.getMessage(), e);
} Prevention
- Validate dynamically built HQL paths against the metamodel in development/profile mode.
- Prefer @Embeddable over @Convert when a value object has fields you navigate to in queries.
- Fail fast in tests: every query a repository layer can emit should have a unit test that parses it.
- Log the exact HQL string when path resolution fails so the offending segment is obvious.
When it happens
Trigger: Writing an HQL/JPQL query that dereferences a basic attribute, e.g. "select e.name.foo from Employee e" when e.name is a String; calling root.get("name").get("x") in the Criteria API; Spring Data JPA derived queries like findByName_Length where the property part is split into nested segments on a basic field; dynamic query builders appending segments to an already-basic path.
Common situations: A nested value object was mapped with an AttributeConverter (@Convert) instead of @Embedded, so the class is BASIC to Hibernate even though the developer thinks of it as structured; an attribute was renamed or moved during refactoring so the old path segment no longer resolves; Spring Data repository method names that accidentally split a single basic field name into multiple parts; copy-pasted queries from a different entity model.
Related errors
- Boolean expression does not support max()
- Boolean expression does not support min()
- Cte root does not have an entity type. Use getReferencedPath
- Embeddable paths cannot be TREAT-ed to an entity type
- Whatever JPA
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/e61591bf3117d870.
Report an issue: GitHub.