{"record":{"id":"8e8ab8d19cae5ba1","repo":"hibernate/hibernate-orm","slug":"entity-discriminator-cannot-be-de-referenced","errorCode":null,"errorMessage":"Entity discriminator cannot be de-referenced","messagePattern":"Entity discriminator cannot be de-referenced","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractDiscriminatorSqmPathSource.java","lineNumber":31,"sourceCode":"\nimport static jakarta.persistence.metamodel.Bindable.BindableType.SINGULAR_ATTRIBUTE;\nimport static jakarta.persistence.metamodel.Type.PersistenceType.BASIC;\nimport static org.hibernate.metamodel.mapping.EntityDiscriminatorMapping.DISCRIMINATOR_ROLE_NAME;\n\n/**\n * Abstract SqmPathSource implementation for discriminators\n *\n * @author Steve Ebersole\n */\npublic abstract class AbstractDiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D>\n\t\timplements ReturnableType<D>, SqmDomainType<D> {\n\tpublic AbstractDiscriminatorSqmPathSource(DomainType<D> domainType) {\n\t\tsuper( DISCRIMINATOR_ROLE_NAME, null, domainType, SINGULAR_ATTRIBUTE );\n\t}\n\n\t@Override\n\tpublic SqmPathSource<?> findSubPathSource(String name) {\n\t\tthrow new IllegalStateException( \"Entity discriminator cannot be de-referenced\" );\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic PersistenceType getPersistenceType() {\n\t\treturn BASIC;\n\t}\n\n\t@Override\n\t@Nonnull\n\tpublic Class<D> getJavaType() {\n\t\treturn getExpressibleJavaType().getJavaTypeClass();\n\t}\n\n\t@Override\n\tpublic @Nullable SqmDomainType<D> getSqmType() {\n\t\treturn this;\n\t}","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/AbstractDiscriminatorSqmPathSource.java#L13-L49","documentation":"The discriminator column of an entity (its 'class' / DTYPE path, exposed as a SqmPathSource with the reserved role \"type\") is a scalar marker, not an embeddable or association. If HQL/Criteria navigation tries to resolve a sub-attribute underneath the discriminator path (findSubPathSource), Hibernate throws IllegalStateException because there is nothing to navigate into.","triggerScenarios":"HQL/Criteria like select p.type.name from Person p, or root.get(\"type\").get(\"name\"), or sqmPath.get(\"class\").get(<anything>) — any dereference of the discriminator path for a SINGLE_TABLE/JOINED inheritance discriminator. Also generated code that recursively expands every path source of an entity, including the synthetic discriminator source.","commonSituations":"Query builders / GraphQL-JVM style resolvers that walk all SqmPathSources of an entity and call findSubPathSource on each name. Assuming the JPA 3.2 TYPE() function returns a navigable object rather than a Class reference. Copying entity graph expansions that work on embeddables onto the discriminator.","solutions":["Treat the discriminator as a leaf: compare it with TYPE(p) = :subtype or p.type = DiscriminatorValue, never navigate through it","If you need fields of the subtype, use TREAT(p AS Subtype).attribute or a join to the subclass entity instead","In generic path-walking code, skip SqmPathSource instances whose getPathName() equals \"type\"/\"class\" or that extend AbstractDiscriminatorSqmPathSource"],"exampleFix":"// before (HQL)\nselect p.type.name from Person p           // illegal dereference\n\n// after\nselect p.name from TREAT(p as Employee) p  // or\nselect type(p) from Person p                // compare, don't navigate","handlingStrategy":"validation","validationCode":"// Before navigating a path source, ensure it is not a discriminator\nString name = pathSource.getPathName();\nif (\"type\".equals(name) || \"class\".equals(name)) {\n    return; // discriminator: leaf node, not navigable\n}","typeGuard":"static boolean isDiscriminatorSource(org.hibernate.query.sqm.tree.SqmPathSource<?> src) {\n    return src instanceof org.hibernate.metamodel.model.domain.internal.AbstractDiscriminatorSqmPathSource<?>;\n}","tryCatchPattern":"try {\n    SqmPathSource<?> sub = source.findSubPathSource(name);\n} catch (IllegalStateException e) {\n    if (\"Entity discriminator cannot be de-referenced\".equals(e.getMessage())) {\n        // skip discriminator navigation; treat as leaf\n    } else throw e;\n}","preventionTips":["Never generate paths under the discriminator; only compare with it","Use TREAT() or joins to reach subclass state","Add a query-builder test suite over an inheritance-mapped test entity"],"tags":["hibernate","hql","discriminator","inheritance","sqm"],"backgroundTag":"query-path-navigation-error","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}