{"record":{"id":"8429210cb1f2eb96","repo":"hibernate/hibernate-orm","slug":"bean-bean-was-not-of-declared-bean-type","errorCode":null,"errorMessage":"Bean [\" + bean + \"] was not of declared bean type [\" + beanClass.getName() + \"]","messagePattern":"Bean \\[\" \\+ bean \\+ \"\\] was not of declared bean type \\[\" \\+ beanClass\\.getName\\(\\) \\+ \"\\]","errorType":"exception","errorClass":"BeanIntrospectionException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/internal/util/beans/BeanInfoHelper.java","lineNumber":71,"sourceCode":"\tpublic interface ReturningBeanInfoDelegate<T> {\n\t\tT processBeanInfo(BeanInfo beanInfo) throws Exception;\n\t}\n\n\tprivate final Class<?> beanClass;\n\tprivate final Class<?> stopClass;\n\n\tpublic BeanInfoHelper(Class<?> beanClass) {\n\t\tthis( beanClass, Object.class );\n\t}\n\n\tpublic BeanInfoHelper(Class<?> beanClass, Class<?> stopClass) {\n\t\tthis.beanClass = beanClass;\n\t\tthis.stopClass = stopClass;\n\t}\n\n\tpublic void applyToBeanInfo(Object bean, BeanInfoDelegate delegate) {\n\t\tif ( ! beanClass.isInstance( bean ) ) {\n\t\t\tthrow new BeanIntrospectionException( \"Bean [\" + bean + \"] was not of declared bean type [\" + beanClass.getName() + \"]\" );\n\t\t}\n\n\t\tvisitBeanInfo( beanClass, stopClass, delegate );\n\t}\n\n\tpublic static void visitBeanInfo(Class<?> beanClass, BeanInfoDelegate delegate) {\n\t\tvisitBeanInfo( beanClass, Object.class, delegate );\n\t}\n\n\tpublic static void visitBeanInfo(Class<?> beanClass, Class<?> stopClass, BeanInfoDelegate delegate) {\n\t\ttry {\n\t\t\tfinal BeanInfo info = getBeanInfo( beanClass, stopClass );\n\t\t\ttry {\n\t\t\t\tdelegate.processBeanInfo( info );\n\t\t\t}\n\t\t\tcatch ( RuntimeException e ) {\n\t\t\t\tthrow e;\n\t\t\t}","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/internal/util/beans/BeanInfoHelper.java#L53-L89","documentation":"BeanInfoHelper caches a BeanInfo for a declared beanClass; applyToBeanInfo(bean, delegate) first asserts the concrete bean really is an instance of that class via beanClass.isInstance(bean). When the check fails it throws BeanIntrospectionException. Because isInstance is a runtime-identity check, two copies of the same class name loaded by different classloaders also fail it despite identical names.","triggerScenarios":"Calling applyToBeanInfo with a bean of an unrelated runtime type (e.g., a Map or a DTO where the entity class was declared), or with an object deserialized or loaded under a different classloader than the one that loaded beanClass.","commonSituations":"App-server redeploys and parent/child classloader splits; objects deserialized with the wrong loader; generic plumbing that loses the static type and passes Object; test fixtures reusing helpers with mismatched bean classes.","solutions":["Pass a bean whose runtime type is beanClass or a subclass of it.","On classloader mismatches, deserialize or load with beanClass's own classloader (or the TCCL) so both sides share one class identity.","Add an instanceof assertion at your boundary with a clear message instead of letting introspection fail."],"exampleFix":"// before\nBeanInfoHelper helper = new BeanInfoHelper(Customer.class);\nhelper.applyToBeanInfo(someMap, info -> { }); // Map is not a Customer -> BeanIntrospectionException\n\n// after\nif (!(someObject instanceof Customer c)) throw new IllegalArgumentException(\"expected Customer\");\nhelper.applyToBeanInfo(c, info -> { });","handlingStrategy":"type-guard","validationCode":"if (!(beanClass.isInstance(bean))) {\n    throw new IllegalArgumentException(\"expected instance of \" + beanClass.getName() + \" but got \" + bean.getClass().getName());\n}\nhelper.applyToBeanInfo(bean, delegate);","typeGuard":"static boolean isInstanceOfClass(Class<?> beanClass, Object bean) {\n    return bean != null && beanClass.isInstance(bean);\n}","tryCatchPattern":"try {\n    helper.applyToBeanInfo(bean, delegate);\n} catch (org.hibernate.internal.util.beans.BeanIntrospectionException e) {\n    // type mismatch: compare bean.getClass().getName() vs beanClass.getName(); equal names -> classloader duplication\n}","preventionTips":["Assert the bean type at your boundary with a clear message.","Ensure beans and their classes share one classloader (deserialization uses the entity class's loader).","Avoid generic Object plumbing around BeanInfoHelper; carry the static type."],"tags":["hibernate","beans","introspection","classloader"],"backgroundTag":"bean-instance-type-mismatch","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}