{"record":{"id":"8567973ec18ea960","repo":"spring-projects/spring-framework","slug":"failed-to-obtain-beaninfo-for-class-beanclass-ge","errorCode":null,"errorMessage":"Failed to obtain BeanInfo for class [{beanClass.getName()}]","messagePattern":"Failed to obtain BeanInfo for class \\[(.+?)\\]","errorType":"exception","errorClass":"FatalBeanException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java","lineNumber":299,"sourceCode":"\t\t\t\t\treadMethodNames.add(readMethod.getName());\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Explicitly check implemented interfaces for setter/getter methods as well,\n\t\t\t// in particular for interface default methods.\n\t\t\tClass<?> currClass = beanClass;\n\t\t\twhile (currClass != null && currClass != Object.class) {\n\t\t\t\tintrospectInterfaces(beanClass, currClass, readMethodNames);\n\t\t\t\tcurrClass = currClass.getSuperclass();\n\t\t\t}\n\n\t\t\t// Check for record-style accessors without prefix: for example, \"lastName()\"\n\t\t\t// - accessor method directly referring to instance field of same name\n\t\t\t// - same convention for component accessors of Java 15 record classes\n\t\t\tintrospectPlainAccessors(beanClass, readMethodNames);\n\t\t}\n\t\tcatch (IntrospectionException ex) {\n\t\t\tthrow new FatalBeanException(\"Failed to obtain BeanInfo for class [\" + beanClass.getName() + \"]\", ex);\n\t\t}\n\t}\n\n\tprivate void introspectInterfaces(Class<?> beanClass, Class<?> currClass, Set<String> readMethodNames)\n\t\t\tthrows IntrospectionException {\n\n\t\tfor (Class<?> ifc : currClass.getInterfaces()) {\n\t\t\tif (!ClassUtils.isJavaLanguageInterface(ifc)) {\n\t\t\t\tfor (PropertyDescriptor pd : getBeanInfo(ifc).getPropertyDescriptors()) {\n\t\t\t\t\tPropertyDescriptor existingPd = this.propertyDescriptors.get(pd.getName());\n\t\t\t\t\tif (existingPd == null ||\n\t\t\t\t\t\t\t(existingPd.getReadMethod() == null && pd.getReadMethod() != null)) {\n\t\t\t\t\t\t// GenericTypeAwarePropertyDescriptor leniently resolves a set* write method\n\t\t\t\t\t\t// against a declared read method, so we prefer read method descriptors here.\n\t\t\t\t\t\tpd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);\n\t\t\t\t\t\tif (pd.getWriteMethod() == null &&\n\t\t\t\t\t\t\t\tisInvalidReadOnlyPropertyType(pd.getPropertyType(), beanClass)) {\n\t\t\t\t\t\t\t// Ignore read-only properties such as ClassLoader - no need to bind to those","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java#L281-L317","documentation":"Thrown as FatalBeanException wrapping a java.beans.IntrospectionException when CachedIntrospectionResults fails to obtain BeanInfo for a class during the initial introspection pass (getBeanInfo(beanClass) or the introspection of methods/interfaces/plained accessors). This typically signals that the JDK Introspector rejected the class's bean metadata.","triggerScenarios":"Triggered when CachedIntrospectionResults.forClass(beanClass) is first created for a BeanWrapper or BeanUtils call, and the underlying java.beans.Introspector.getBeanInfo throws IntrospectionException (e.g. mismatched getter/setter types, an indexed property descriptor that could not be built).","commonSituations":"A class has getter/setter pairs with incompatible types for the same property name, an overloaded indexed accessor with non-int index, or a class generated by a code generator/bytecode library that emits methods the Introspector cannot reconcile. Frequently seen with Lombok @Delegate or with manually written conflicting accessors.","solutions":["Inspect the wrapped IntrospectionException cause to identify the offending property/method.","Fix conflicting getter/setter signatures (matching types, int index for indexed accessors).","Exclude or rename the conflicting accessor that is confusing the Introspector.","If unavoidable, avoid wrapping that class directly with a BeanWrapper; use field access (DirectFieldAccessor) or map it manually."],"exampleFix":"// before\n// class has: String getName(); void setName(int name);  -> conflicting types\nBeanWrapper wrapper = new BeanWrapperImpl(myBean);\n\n// after - align accessor types\n// String getName(); void setName(String name);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"static boolean introspectable(Class<?> c) {\n    try { java.beans.Introspector.getBeanInfo(c); return true; }\n    catch (java.beans.IntrospectionException e) { return false; }\n}","tryCatchPattern":"try {\n    BeanWrapper w = new BeanWrapperImpl(bean);\n} catch (FatalBeanException ex) {\n    // cause is IntrospectionException; identify the offending property\n    log.error(\"introspection failed for {}\", bean.getClass(), ex.getCause());\n}","preventionTips":["Keep getter/setter types consistent per property name.","Run a quick java.beans.Introspector.getBeanInfo(cls) smoke test in unit tests for shared DTOs.","Avoid conflicting overloaded accessors that the Introspector cannot reconcile."],"tags":["introspection","bean-wrapper","spring-beans"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}