spring-projects/spring-framework · error · FatalBeanException

Failed to re-introspect class [${beanClass.getName()}]

Error message

Failed to re-introspect class [${beanClass.getName()}]

What it means

FatalBeanException thrown from buildGenericTypeAwarePropertyDescriptor when constructing a GenericTypeAwarePropertyDescriptor raises IntrospectionException - i.e. re-introspecting a single property descriptor against its declaring class failed. This is a narrower failure than [164]: the overall BeanInfo was obtained, but Spring's generic-type-aware wrapper could not reconcile this particular descriptor's read/write methods.

Source

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

			pd = this.propertyDescriptors.get(StringUtils.uncapitalize(name));
			if (pd == null) {
				pd = this.propertyDescriptors.get(StringUtils.capitalize(name));
			}
		}
		return pd;
	}

	PropertyDescriptor[] getPropertyDescriptors() {
		return this.propertyDescriptors.values().toArray(PropertyDescriptorUtils.EMPTY_PROPERTY_DESCRIPTOR_ARRAY);
	}

	private PropertyDescriptor buildGenericTypeAwarePropertyDescriptor(Class<?> beanClass, PropertyDescriptor pd) {
		try {
			return new GenericTypeAwarePropertyDescriptor(beanClass, pd.getName(), pd.getReadMethod(),
					pd.getWriteMethod(), pd.getPropertyEditorClass());
		}
		catch (IntrospectionException ex) {
			throw new FatalBeanException("Failed to re-introspect class [" + beanClass.getName() + "]", ex);
		}
	}

}

View on GitHub (pinned to e8729d0438)

Solutions

  1. Read the cause for the offending descriptor name and method pair.
  2. Make the read and write method signatures (including generics) consistent across the hierarchy.
  3. If Lombok-generated, recompile with a current Lombok and verify accessor shapes with javap.
  4. Exclude the offending property from introspection by removing or renaming one of the conflicting methods.

Example fix

// before
public interface Repo<T> { T getEntity(); void setEntity(Object o); }
// cause: incompatible generic pair on GenericTypeAwarePropertyDescriptor

// after
public interface Repo<T> { T getEntity(); void setEntity(T o); }
Defensive patterns

Strategy: try-catch

Validate before calling

// Detect generic incompatibility before relying on Spring introspection
java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(MyClass.class);
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
    Class<?> rt = pd.getReadMethod() == null ? null : pd.getReadMethod().getReturnType();
    Class<?> wt = pd.getWriteMethod() == null ? null
        : pd.getWriteMethod().getParameterTypes()[0];
    if (rt != null && wt != null && !rt.isAssignableFrom(wt) && !wt.isAssignableFrom(rt)) {
        throw new IllegalStateException("Incompatible accessors on " + pd.getName());
    }
}

Type guard

static boolean hasConsistentGenericAccessors(Class<?> c) {
    try {
        for (PropertyDescriptor pd : java.beans.Introspector.getBeanInfo(c).getPropertyDescriptors()) {
            if (pd.getReadMethod() != null && pd.getWriteMethod() != null) {
                Class<?> r = pd.getReadMethod().getReturnType();
                Class<?> w = pd.getWriteMethod().getParameterTypes()[0];
                if (!r.isAssignableFrom(w) && !w.isAssignableFrom(r)) return false;
            }
        }
        return true;
    } catch (Exception e) { return false; }
}

Try / catch

try {
    return CachedIntrospectionResults.forClass(beanClass);
} catch (FatalBeanException ex) {
    if (ex.getMessage().startsWith("Failed to re-introspect")) {
        log.error("Re-introspection failed on {} - likely generic mismatch", beanClass.getName(), ex.getCause());
    }
    throw ex;
}

Prevention

When it happens

Trigger: CachedIntrospectionResults building a GenericTypeAwarePropertyDescriptor for a property whose read and write methods have incompatible generic signatures or where setReadMethod/setWriteMethod on the descriptor raises IntrospectionException during construction.

Common situations: Generic bean with parameterized accessors where the type variables resolve inconsistently across an inheritance hierarchy; interface default methods combined with class methods producing an incompatible pair; rarely, classes woven by AspectJ or generated by Lombok @Builder/@Accessors producing non-standard accessor shapes.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/290305ea3a361223.json. Report an issue: GitHub.