{"record":{"id":"02e155e252f65abe","repo":"hibernate/hibernate-orm","slug":"basic-value-cannot-be-treated-downcast","errorCode":null,"errorMessage":"Basic-value cannot be treated (downcast)","messagePattern":"Basic-value cannot be treated \\(downcast\\)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmBasicValuedSimplePath.java","lineNumber":187,"sourceCode":"\n\tprivate @Nullable Class<?> getJavaTypeClass(SqmDomainType<T> sqmPathType) {\n\t\tfinal SqmBindableType<T> expressible = nodeBuilder().resolveExpressible( sqmPathType );\n\t\treturn expressible == null ? null : expressible.getRelationalJavaType().getJavaTypeClass();\n\t}\n\n\n\t// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\t// SqmPath\n\n\t@Override\n\tpublic @Nonnull BasicJavaType<T> getJavaTypeDescriptor() {\n\t\treturn (BasicJavaType<T>) super.getJavaTypeDescriptor();\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <S extends T> SqmTreatedPath<T,S> treatAs(@Nonnull Class<S> treatJavaType) {\n\t\tthrow new UnsupportedOperationException( \"Basic-value cannot be treated (downcast)\" );\n\t}\n\n\t@Nonnull\n\t@Override\n\tpublic <S extends T> SqmTreatedPath<T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget) {\n\t\tthrow new UnsupportedOperationException( \"Basic-value cannot be treated (downcast)\" );\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <S extends T> SqmTreatedPath<T, S> treatAs(@Nonnull Class<S> treatJavaType, @Nullable String alias) {\n\t\tthrow new UnsupportedOperationException( \"Basic-value cannot be treated (downcast)\" );\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic <S extends T> SqmTreatedPath<T, S> treatAs(@Nonnull EntityDomainType<S> treatTarget, @Nullable String alias) {\n\t\tthrow new UnsupportedOperationException( \"Basic-value cannot be treated (downcast)\" );","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmBasicValuedSimplePath.java#L169-L205","documentation":"SqmBasicValuedSimplePath.treatAs(Class) throws UnsupportedOperationException because TREAT (downcasting a path to a subclass) is only defined for entity-typed paths participating in an inheritance hierarchy. A basic-valued path (String, number, enum, converted object) has no subtype hierarchy, so no treat operation can exist. The exception is raised while the SQM tree is built, i.e. before SQL rendering.","triggerScenarios":"HQL \"select treat(p.name as Brand) from Person p\" where p.name is a basic String attribute; Criteria code calling path.treatAs(SomeClass.class) on root.get(\"code\") where code is basic; generic frameworks that call treatAs on every path implementing JpaPath; applying treat to an @Convert-mapped value object.","commonSituations":"A value class (e.g. BrandName) looks like an entity to the author but is persisted as a basic column via AttributeConverter; refactoring moved a related entity to a basic column (or vice versa) and old treat() queries still target it; query built by composing treat on an arbitrary join without checking its type; upgrading code that used treat only on entity joins to also treat attribute paths.","solutions":["Apply treat to the entity path instead: \"treat(p as Brand)\" or root.join(\"brand\").treatAs(Brand.class), where brand is an association.","If the value needs subtype handling, map it as an entity (@Entity with inheritance) or @Embeddable rather than basic + @Convert.","Remove the treat and express the filter with a where condition or a type() predicate on the owning entity.","Audit all TREAT usages after changing an attribute between basic and association mapping."],"exampleFix":"// before - name is a basic String column -> UnsupportedOperationException\nJpaPath<Brand> b = root.<String>get(\"name\").treatAs(Brand.class);\n\n// after - treat an actual entity association join\nJpaJoin<Object, Brand> b = root.join(\"brand\").treatAs(Brand.class);","handlingStrategy":"type-guard","validationCode":"// treat is legal only on entity-typed attributes\nstatic boolean canTreat(jakarta.persistence.metamodel.ManagedType<?> owner, String attrName) {\n    return owner.getAttribute(attrName).getPersistentAttributeType()\n            == jakarta.persistence.metamodel.Attribute.PersistentAttributeType.ENTITY;\n}","typeGuard":"static boolean isEntityValued(jakarta.persistence.criteria.Path<?> path) {\n    return path.getJavaType() != null\n        && jakarta.persistence.metamodel.EntityType.class.isAssignableFrom(path.getJavaType()) == false\n        ? false\n        : true;\n}\n// Prefer the attribute check above; java type alone is not a reliable discriminator for treat.","tryCatchPattern":"try {\n    JpaPath<Treated> t = (JpaPath<Treated>) base.treatAs(Treated.class);\n} catch (UnsupportedOperationException e) {\n    throw new IllegalArgumentException(\"treat() applied to non-entity path \" + base, e);\n}","preventionTips":["Reserve TREAT for entity roots and association joins.","In generic code, check PersistentAttributeType.ENTITY before emitting treat.","Review TREAT usages whenever an association mapping is flattened to a basic column.","Map value objects needing subtype behavior as entities, not @Convert basics."],"tags":["hibernate","hql","sqm","treat","downcast","inheritance"],"backgroundTag":"hql-treat-downcast-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}