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);
	}

	@Override

View on GitHub (pinned to e8729d0438)

Solutions

  1. Verify the property name matches a public getter/setter exactly (case-sensitive, 'foo' -> getFoo/isFoo/setFoo).
  2. If using @ConfigurationProperties, regenerate metadata and confirm the field has standard accessors.
  3. Switch to a field-access BeanWrapper (DirectFieldAccessor) if the field is private with no accessor.
  4. 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

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


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