spring-projects/spring-framework · error · FatalBeanException

Failed to obtain BeanInfo for class [{beanClass.getName()}]

Error message

Failed to obtain BeanInfo for class [{beanClass.getName()}]

What it means

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.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/CachedIntrospectionResults.java:299

					readMethodNames.add(readMethod.getName());
				}
			}

			// Explicitly check implemented interfaces for setter/getter methods as well,
			// in particular for interface default methods.
			Class<?> currClass = beanClass;
			while (currClass != null && currClass != Object.class) {
				introspectInterfaces(beanClass, currClass, readMethodNames);
				currClass = currClass.getSuperclass();
			}

			// Check for record-style accessors without prefix: for example, "lastName()"
			// - accessor method directly referring to instance field of same name
			// - same convention for component accessors of Java 15 record classes
			introspectPlainAccessors(beanClass, readMethodNames);
		}
		catch (IntrospectionException ex) {
			throw new FatalBeanException("Failed to obtain BeanInfo for class [" + beanClass.getName() + "]", ex);
		}
	}

	private void introspectInterfaces(Class<?> beanClass, Class<?> currClass, Set<String> readMethodNames)
			throws IntrospectionException {

		for (Class<?> ifc : currClass.getInterfaces()) {
			if (!ClassUtils.isJavaLanguageInterface(ifc)) {
				for (PropertyDescriptor pd : getBeanInfo(ifc).getPropertyDescriptors()) {
					PropertyDescriptor existingPd = this.propertyDescriptors.get(pd.getName());
					if (existingPd == null ||
							(existingPd.getReadMethod() == null && pd.getReadMethod() != null)) {
						// GenericTypeAwarePropertyDescriptor leniently resolves a set* write method
						// against a declared read method, so we prefer read method descriptors here.
						pd = buildGenericTypeAwarePropertyDescriptor(beanClass, pd);
						if (pd.getWriteMethod() == null &&
								isInvalidReadOnlyPropertyType(pd.getPropertyType(), beanClass)) {
							// Ignore read-only properties such as ClassLoader - no need to bind to those

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Inspect the wrapped IntrospectionException cause to identify the offending property/method.
  2. Fix conflicting getter/setter signatures (matching types, int index for indexed accessors).
  3. Exclude or rename the conflicting accessor that is confusing the Introspector.
  4. If unavoidable, avoid wrapping that class directly with a BeanWrapper; use field access (DirectFieldAccessor) or map it manually.

Example fix

// before
// class has: String getName(); void setName(int name);  -> conflicting types
BeanWrapper wrapper = new BeanWrapperImpl(myBean);

// after - align accessor types
// String getName(); void setName(String name);
Defensive patterns

Strategy: try-catch

Type guard

static boolean introspectable(Class<?> c) {
    try { java.beans.Introspector.getBeanInfo(c); return true; }
    catch (java.beans.IntrospectionException e) { return false; }
}

Try / catch

try {
    BeanWrapper w = new BeanWrapperImpl(bean);
} catch (FatalBeanException ex) {
    // cause is IntrospectionException; identify the offending property
    log.error("introspection failed for {}", bean.getClass(), ex.getCause());
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/8567973ec18ea960. Report an issue: GitHub.