{"record":{"id":"661a3b8c2aa818af","repo":"hibernate/hibernate-orm","slug":"cannot-interpret-discriminator-value-discriminat","errorCode":null,"errorMessage":"Cannot interpret discriminator value ({discriminatorRole}) : {discriminatorValue}","messagePattern":"Cannot interpret discriminator value \\((.+?)\\) : (.+?)","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/metamodel/internal/FullNameImplicitDiscriminatorStrategy.java","lineNumber":35,"sourceCode":" */\npublic class FullNameImplicitDiscriminatorStrategy implements ImplicitDiscriminatorStrategy {\n\tpublic static final FullNameImplicitDiscriminatorStrategy FULL_NAME_STRATEGY = new FullNameImplicitDiscriminatorStrategy();\n\n\t@Override\n\tpublic Object toDiscriminatorValue(EntityMappingType entityMapping, NavigableRole discriminatorRole, MappingMetamodelImplementor mappingModel) {\n\t\treturn entityMapping.getEntityName();\n\t}\n\n\t@Override\n\tpublic EntityMappingType toEntityMapping(Object discriminatorValue, NavigableRole discriminatorRole, MappingMetamodelImplementor mappingModel) {\n\t\tif ( discriminatorValue instanceof String assumedEntityName ) {\n\t\t\tfinal var persister = mappingModel.findEntityDescriptor( assumedEntityName );\n\t\t\tif ( persister != null ) {\n\t\t\t\treturn persister;\n\t\t\t}\n\t\t}\n\n\t\tthrow new HibernateException( \"Cannot interpret discriminator value (\" + discriminatorRole + \") : \" + discriminatorValue );\n\t}\n}\n","sourceCodeStart":17,"sourceCodeEnd":38,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/metamodel/internal/FullNameImplicitDiscriminatorStrategy.java#L17-L38","documentation":"Thrown by FullNameImplicitDiscriminatorStrategy.toEntityMapping when a discriminator value read from data cannot be translated into a mapped EntityMappingType. This strategy (used for inheritance mappings without an explicit discriminator, where the discriminator is effectively the entity name) accepts only String values that resolve via mappingModel.findEntityDescriptor(...); anything else - a non-String value, an unregistered name, wrong casing, qualified vs. unqualified mismatch - fails with this HibernateException echoing the discriminator role and the offending value.","triggerScenarios":"Reading inheritance-hierarchy rows whose discriminator/name column contains a value that is not a currently mapped entity name (entity renamed or moved packages between releases, legacy data, manually inserted rows); discriminator stored fully-qualified while mapping registers short names or vice versa; enum/native integer values left in a column the implicit strategy treats as entity names.","commonSituations":"Refactoring entity class names or packages after go-live without a data migration; environments restored from old backups into new schemas; queries over polymorphic hierarchies (table-per-class / implicit polymorphism) hitting stale discriminator data.","solutions":["Compare the value printed in the message with the registered entity names (sessionFactory.getMetamodel().getEntityNames() or entity descriptors)","Migrate the stored discriminator values to match the current entity names (UPDATE ... or a startup fixer script)","If the value is legitimately not an entity name, switch the mapping to an explicit @DiscriminatorColumn/@DiscriminatorValue scheme instead of the implicit full-name strategy","Keep entity names stable across refactors by explicitly naming entities (@Entity(name=...)) so renames do not change discriminator data"],"exampleFix":"// before - entity renamed, old rows keep the old name\n@Entity(name = \"BillingDoc\")            // rows still store 'BillingDocument'\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic abstract class BillingDocument { ... }\n\n// after - pin a stable entity name\n@Entity(name = \"BillingDocument\")       // matches stored discriminator data\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic abstract class BillingDocument { ... }\n\n// or migrate the data\n-- UPDATE docs SET dtype = 'BillingDoc' WHERE dtype = 'BillingDocument';","handlingStrategy":"validation","validationCode":"// Startup check: every stored discriminator value must resolve to a mapped entity\nSet<String> registered = emf.getMetamodel().getEntities().stream().map(EntityType::getName).collect(toSet());\nfor ( String stored : jdbc.queryForList(\"SELECT DISTINCT dtype FROM docs\", String.class) ) {\n    if ( !registered.contains(stored) ) {\n        throw new IllegalStateException(\"Unmapped discriminator value in data: '\" + stored + \"'\");\n    }\n}","typeGuard":"static boolean isKnownEntityName(Metamodel mm, Object discriminatorValue) {\n    if (!(discriminatorValue instanceof String name)) return false;\n    try { mm.entity(name); return true; } catch (IllegalArgumentException e) { return false; }\n}","tryCatchPattern":"try {\n    return em.createQuery(\"select d from BillingDocument d\", BillingDocument.class).getResultList();\n}\ncatch ( org.hibernate.HibernateException e ) {\n    if ( e.getMessage() != null && e.getMessage().contains(\"Cannot interpret discriminator value\") ) {\n        throw new DataMigrationNeeded(\"Stored discriminator no longer matches mapped entity names: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Pin stable entity names with @Entity(name = \"...\") so class/package refactors never touch stored data","Add data-migration updates whenever renaming entities in polymorphic hierarchies","Include a discriminator-value audit in migration checklists and CI datasets"],"tags":["hibernate","inheritance","discriminator","polymorphism","data-migration"],"backgroundTag":"discriminator-value-unresolvable","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}