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
- Read the cause for the offending descriptor name and method pair.
- Make the read and write method signatures (including generics) consistent across the hierarchy.
- If Lombok-generated, recompile with a current Lombok and verify accessor shapes with javap.
- 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
- Keep generic accessors consistent across inheritance hierarchies.
- Recompile generated code (Lombok/MapStruct) when changing generic signatures.
- Test introspection of parameterized beans explicitly.
- Avoid mixing interface default methods with class methods that conflict on a property.
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
- Failed to obtain BeanInfo for class [${beanClass.getName()}]
- Bean property '{propertyName}' is not readable or has an inv
- No property '${propertyName}' found
- Write method must have exactly 1 or 2 parameters: ${method}
- Bad read method arg count: ${readMethod}
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/290305ea3a361223.json.
Report an issue: GitHub.