{"record":{"id":"4d26ef53b2632640","repo":"hibernate/hibernate-orm","slug":"expected-object-of-type-s-but-found-s-disc-4d26ef","errorCode":null,"errorMessage":"Expected object of type `%s`, but found `%s`; discriminator = %s","messagePattern":"Expected object of type `(.+?)`, but found `(.+?)`; discriminator = (.+?)","errorType":"exception","errorClass":"WrongClassException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java","lineNumber":1054,"sourceCode":"\t\t}\n\t\telse {\n\t\t\tassert entityDescriptor.hasSubclasses()\n\t\t\t\t\t: \"Reading a discriminator from a result set should only happen if the entity has subclasses\";\n\t\t\tfinal var discriminatorMapping = entityDescriptor.getDiscriminatorMapping();\n\t\t\tassert discriminatorMapping != null;\n\t\t\tfinal Object discriminator = discriminatorAssembler.extractRawValue( rowProcessingState );\n\t\t\tfinal var discriminatorDetails = discriminatorMapping.resolveDiscriminatorValue( discriminator );\n\t\t\tif ( discriminatorDetails == null ) {\n\t\t\t\tassert discriminator == null : \"Discriminator details should only be null for null values\";\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tfinal var indicatedEntity = discriminatorDetails.getIndicatedEntity();\n\t\t\t\tif ( indicatedEntity.isTypeOrSuperType( entityDescriptor ) ) {\n\t\t\t\t\treturn indicatedEntity.getEntityPersister();\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow new WrongClassException(\n\t\t\t\t\t\t\tindicatedEntity.getEntityName(),\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\tentityDescriptor.getEntityName(),\n\t\t\t\t\t\t\tdiscriminator\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected boolean useEmbeddedIdentifierInstanceAsEntity(EntityInitializerData data) {\n\t\tif ( data.canUseEmbeddedIdentifierInstanceAsEntity ) {\n\t\t\tdata.concreteDescriptor =\n\t\t\t\t\tdetermineConcreteEntityDescriptor( data.getRowProcessingState(),\n\t\t\t\t\t\t\tdiscriminatorAssembler, entityDescriptor );\n\t\t\treturn data.concreteDescriptor != null\n\t\t\t\t&& data.concreteDescriptor.isInstance( data.getRowProcessingState().getEntityId() );\n\t\t}","sourceCodeStart":1036,"sourceCodeEnd":1072,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityInitializerImpl.java#L1036-L1072","documentation":"When an entity initializer reads a discriminator to pick the concrete persister (resolveConcreteDescriptor), it calls discriminatorMapping.resolveDiscriminatorValue(discriminator) and then checks indicatedEntity.isTypeOrSuperType(entityDescriptor). If the class the discriminator indicates is not the expected type or a subtype of it, Hibernate throws WrongClassException('Expected object of type X, but found Y; discriminator = <value>'). The row claims an inheritance type that does not fit where the row was found.","triggerScenarios":"A polymorphic association declared against class A, but the row's discriminator denotes class B outside A's hierarchy branch; discriminator strings in the DB not matching any @DiscriminatorValue (e.g. after renaming entities or discriminator values); manually inserted rows with a wrong discriminator; joined-inheritance data where subclass rows and discriminators disagree.","commonSituations":"Refactoring or renaming entity names / @DiscriminatorValue strings without migrating existing rows; multi-module apps where one module inserts rows with discriminators another module's mapping does not know; copy-pasted data between environments; adding a new subclass to one deployment while older rows reference a removed branch.","solutions":["Compare the reported discriminator value with your @DiscriminatorValue mapping and UPDATE the rows to a valid, matching value.","If the row legitimately belongs to a different branch, correct the declared association type to the common superclass of all possible targets.","After renaming entities/discriminator values, run a data migration (UPDATE ... SET dtype = 'NewName' WHERE dtype = 'OldName').","Verify the inheritance mapping (@Inheritance(strategy=...), @DiscriminatorColumn) matches how the data was written."],"exampleFix":"-- before: rows carry a discriminator Hibernate cannot map onto the expected hierarchy\nUPDATE document SET dtype = 'CONTRACT' WHERE dtype = 'AGR_CONTRACT';\n\n// before (association declared too narrow for the data present)\n@ManyToOne(targetEntity = Contract.class)\nprivate Contract document;\n\n// after (declare the branch the data actually contains, or the common base)\n@ManyToOne(targetEntity = LegalDocument.class)\nprivate LegalDocument document;","handlingStrategy":"validation","validationCode":"// Compare distinct discriminator values in the DB against the mapped ones\nMap<String, Class<?>> allowed = Map.of(\"DOG\", Dog.class, \"CAT\", Cat.class); // your @DiscriminatorValues\nList<Object> distinct = em.createNativeQuery(\"select distinct dtype from animal\").getResultList();\nfor (Object d : distinct) {\n    if (d == null || !allowed.containsKey(d.toString())) {\n        throw new IllegalStateException(\"Unknown discriminator value in animal: \" + d);\n    }\n}","typeGuard":"// Narrow loaded polymorphic values before use\nif (document instanceof Contract c) { ... } // pattern-match the concrete branch\n\nboolean fitsExpectedBranch(Class<?> rowType, Class<?> expected) {\n    return expected.isAssignableFrom(rowType);\n}","tryCatchPattern":"try {\n    List<LegalDocument> docs = em.createQuery(\"select d from LegalDocument d\", LegalDocument.class).getResultList();\n} catch (WrongClassException e) {\n    // e.getExpectedClassName() / e.getActualClassName() / e.getDiscriminator()\n    // quarantine the row or widen the declared association type\n}","preventionTips":["Migrate discriminator values whenever you rename entities or @DiscriminatorValue strings.","Add a CHECK constraint or lookup table on the discriminator column.","Assert association target types cover every discriminator branch the data actually contains.","Integration-test polymorphic loading with every subclass row present."],"tags":["hibernate","orm","inheritance","discriminator","polymorphism","wrong-class-exception","data-integrity"],"backgroundTag":"discriminator-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}