{"record":{"id":"e91a1d70ff85b664","repo":"hibernate/hibernate-orm","slug":"correlated-derived-root-does-not-have-an-entity-ty","errorCode":null,"errorMessage":"Correlated derived root does not have an entity type. Use getReferencedPathSource() instead.","messagePattern":"Correlated derived root does not have an entity type\\. Use getReferencedPathSource\\(\\) instead\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmCorrelatedDerivedRoot.java","lineNumber":54,"sourceCode":"\t\tfinal var existing = context.getCopy( this );\n\t\tif ( existing != null ) {\n\t\t\treturn existing;\n\t\t}\n\t\tfinal var path = context.registerCopy(\n\t\t\t\tthis,\n\t\t\t\tnew SqmCorrelatedDerivedRoot<>( getCorrelationParent().copy( context ) )\n\t\t);\n\t\tcopyTo( path, context );\n\t\treturn path;\n\t}\n\n\t// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\t// JPA\n\n\t@Nonnull\n\t@Override\n\tpublic SqmEntityDomainType<T> getModel() {\n\t\tthrow new UnsupportedOperationException( \"Correlated derived root does not have an entity type. Use getReferencedPathSource() instead.\" );\n\t}\n\n\t@Override\n\tpublic String getEntityName() {\n\t\tthrow new UnsupportedOperationException( \"Correlated derived root does not have an entity type. Use getReferencedPathSource() instead.\" );\n\t}\n\n\t@Override\n\tpublic SqmPathSource<T> getResolvedModel() {\n\t\treturn getReferencedPathSource();\n\t}\n\n}\n","sourceCodeStart":36,"sourceCodeEnd":68,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/domain/SqmCorrelatedDerivedRoot.java#L36-L68","documentation":"SqmCorrelatedDerivedRoot wraps a subquery root that was correlated into an inner query and whose outer referent is a derived root (a \"from (select ...)\" group, often created via SqmCteRoot.createCorrelation() or correlating a derived root inside a subquery). Such a root denotes query-derived rows, not a mapped entity, so the JPA Root contract getModel() (returning an EntityType) cannot be honored; Hibernate throws UnsupportedOperationException and the message tells you to use getReferencedPathSource() to inspect the row type instead.","triggerScenarios":"HQL with a derived table correlated into a subquery, e.g. \"select e from Employee e where exists (select 1 from (select ...) d where d.x = e.x)\" combined with Java code that calls root.getModel() on the subquery root; Criteria code doing subquery.correlate(derivedRoot).getModel(); generic framework code (Specifications, auditors, entity-graph appliers) that unconditionally calls getModel() on every root of every query.","commonSituations":"Spring Data JPA or in-house specification layers that resolve root.getModel().getName() for aliasing or logging on arbitrary queries; migrating queries from entity roots to CTE/derived-table style (Hibernate 6.6+/7 improved support) and legacy root-processing code breaking; correlation of a CTE root (SqmCteRoot.createCorrelation returns SqmCorrelatedDerivedRoot).","solutions":["Use getReferencedPathSource() (or getResolvedModel(), which delegates to it) to obtain the SqmPathSource describing the derived rows.","Guard generic root-handling code: skip or special-case roots that are SqmDerivedRoot, SqmCteRoot, or SqmCorrelatedDerivedRoot before calling getModel().","When an EntityType is genuinely required, query the underlying mapped entity directly instead of a derived table.","Catch UnsupportedOperationException as a last resort in framework code and fall back to getJavaType() metadata."],"exampleFix":"// before - breaks when the correlated root wraps a derived/CTE root\nEntityType<?> t = (EntityType<?>) root.getModel();\nString name = t.getName();\n\n// after - ask for the referenced path source, which always exists\nString name = ((org.hibernate.query.sqm.tree.spi.domain.SqmPath<?>) root)\n        .getReferencedPathSource().getPathName();","handlingStrategy":"type-guard","validationCode":"// In generic root walkers, probe for entity-backed roots before using getModel()\nstatic boolean hasEntityType(jakarta.persistence.criteria.Root<?> root) {\n    return !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmCorrelatedDerivedRoot)\n        && !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmDerivedRoot)\n        && !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmCteRoot)\n        && !(root instanceof org.hibernate.query.sqm.tree.spi.domain.SqmFunctionRoot);\n}","typeGuard":"static boolean isEntityBackedRoot(Object sqmRoot) {\n    return sqmRoot instanceof org.hibernate.query.sqm.tree.spi.from.SqmRoot\n        || sqmRoot instanceof org.hibernate.query.sqm.tree.spi.from.SqmCrossJoin\n        || sqmRoot instanceof org.hibernate.query.sqm.tree.spi.from.SqmEntityJoin;\n}","tryCatchPattern":"try {\n    return root.getModel();\n} catch (UnsupportedOperationException e) {\n    // derived/CTE/correlated-derived roots: no EntityType available\n    return null; // caller falls back to getReferencedPathSource() / getJavaType()\n}","preventionTips":["Never call getModel() unconditionally on roots received from arbitrary queries.","Prefer getResolvedModel()/getReferencedPathSource() which works for all root kinds.","Add CTE and derived-table queries to the corpus your framework tests against.","Treat 'UnsupportedOperationException from getModel' as a missing-type-check code smell, not a runtime hazard to swallow."],"tags":["hibernate","sqm","criteria-api","derived-root","correlation","subquery"],"backgroundTag":"derived-root-no-entity-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}