spring-projects/spring-framework · error · InvalidPropertyException
No property '${propertyName}' found
Error message
No property '${propertyName}' found What it means
Thrown by BeanWrapperImpl.convertForProperty (InvalidPropertyException) when CachedIntrospectionResults.getPropertyDescriptor returns null for the requested property name. It means the JavaBeans Introspector found no accessor matching that exact name on the wrapped class, so Spring cannot determine a target type to convert to.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/BeanWrapperImpl.java:184
return this.cachedIntrospectionResults;
}
/**
* Convert the given value for the specified property to the latter's type.
* <p>This method is only intended for optimizations in a BeanFactory.
* Use the {@code convertIfNecessary} methods for programmatic conversion.
* @param value the value to convert
* @param propertyName the target property
* (note that nested or indexed properties are not supported here)
* @return the new value, possibly the result of type conversion
* @throws TypeMismatchException if type conversion failed
*/
public @Nullable Object convertForProperty(@Nullable Object value, String propertyName) throws TypeMismatchException {
CachedIntrospectionResults cachedIntrospectionResults = getCachedIntrospectionResults();
PropertyDescriptor pd = cachedIntrospectionResults.getPropertyDescriptor(propertyName);
if (pd == null) {
throw new InvalidPropertyException(getRootClass(), getNestedPath() + propertyName,
"No property '" + propertyName + "' found");
}
TypeDescriptor td = ((GenericTypeAwarePropertyDescriptor) pd).getTypeDescriptor();
return convertForProperty(propertyName, null, value, td);
}
@Override
protected @Nullable PropertyHandler getLocalPropertyHandler(String propertyName) {
PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(propertyName);
return (pd != null ? new BeanPropertyHandler((GenericTypeAwarePropertyDescriptor) pd) : null);
}
@Override
protected BeanWrapperImpl newNestedPropertyAccessor(Object object, String nestedPath) {
return new BeanWrapperImpl(object, nestedPath, this);
}
@OverrideView on GitHub (pinned to e8729d0438)
Solutions
- Verify the property name matches a public getter/setter exactly (case-sensitive, 'foo' -> getFoo/isFoo/setFoo).
- If using @ConfigurationProperties, regenerate metadata and confirm the field has standard accessors.
- Switch to a field-access BeanWrapper (DirectFieldAccessor) if the field is private with no accessor.
- Use PropertyMatches.forProperty(...) to surface the closest matches and catch typos.
Example fix
// before
wrapper.convertForProperty(value, "firtName"); // typo
// after
wrapper.convertForProperty(value, "firstName");
// or discover the right name
String[] hints = PropertyMatches.forProperty("firtName", clazz).getPossibleMatches(); Defensive patterns
Strategy: validation
Validate before calling
// Verify the property exists before converting
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(wrapper.getWrappedClass(), propertyName);
if (pd == null) {
throw new IllegalArgumentException("No such property: " + propertyName
+ " on " + wrapper.getWrappedClass().getName());
}
wrapper.convertForProperty(value, propertyName); Type guard
static boolean hasReadableProperty(ConfigurablePropertyAccessor wrapper, String name) {
return wrapper.isReadableProperty(name);
} Try / catch
try {
return wrapper.convertForProperty(value, propertyName);
} catch (InvalidPropertyException ex) {
// PropertyMatches surfaces closest existing names
PropertyMatches pm = PropertyMatches.forProperty(propertyName, wrapper.getWrappedClass());
throw new IllegalArgumentException(pm.buildErrorMessage(), ex);
} Prevention
- Centralize property name constants instead of passing string literals.
- Generate @ConfigurationProperties metadata so IDEs flag invalid keys.
- For dynamic names, always call isReadableProperty/isWritableProperty first.
- Unit-test property paths after renames.
When it happens
Trigger: Calling beanWrapper.convertForProperty(value, "foo") or a SpEL/property binding path where 'foo' has no getFoo/setFoo/getisFoo accessor on the wrapped class; using a typo; targeting a field that exists but has no public accessor (e.g. private field with no getter).
Common situations: YAML/properties binding to a key the @ConfigurationProperties class renamed or never had; refactor left stale property keys; Kotlin class with private backing field and no JVM-visible getter; record component name mismatch (case sensitivity).
Related errors
- Bean property '{propertyName}' is not readable or has an inv
- Failed to obtain BeanInfo for class [${beanClass.getName()}]
- Failed to re-introspect class [${beanClass.getName()}]
- 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/5d60d1d0cfd878ab.json.
Report an issue: GitHub.