spring-projects/spring-framework · error · NotReadablePropertyException

Bean property '{propertyName}' is not readable or has an inv

Error message

Bean property '{propertyName}' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

What it means

The default message of NotReadablePropertyException, raised in getPropertyValue(PropertyTokenHolder) when getLocalPropertyHandler(actualName) returns null or reports !ph.isReadable(). The hint about getter/setter type mismatch refers to BeanWrapperIntrospection: a setter whose parameter type does not match the getter return type can cause the property to be treated as non-readable. So the property either does not exist or its accessor pair is inconsistent.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java:603

			throws TypeMismatchException {

		return convertIfNecessary(propertyName, oldValue, newValue, td.getType(), td);
	}

	@Override
	public @Nullable Object getPropertyValue(String propertyName) throws BeansException {
		AbstractNestablePropertyAccessor nestedPa = getPropertyAccessorForPropertyPath(propertyName);
		PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
		return nestedPa.getPropertyValue(tokens);
	}

	@SuppressWarnings({"rawtypes", "unchecked"})
	protected @Nullable Object getPropertyValue(PropertyTokenHolder tokens) throws BeansException {
		String propertyName = tokens.canonicalName;
		String actualName = tokens.actualName;
		PropertyHandler ph = getLocalPropertyHandler(actualName);
		if (ph == null || !ph.isReadable()) {
			throw new NotReadablePropertyException(getRootClass(), this.nestedPath + propertyName);
		}
		try {
			Object value = ph.getValue();
			if (tokens.keys != null) {
				if (value == null) {
					if (isAutoGrowNestedPaths()) {
						value = setDefaultValue(new PropertyTokenHolder(tokens.actualName));
					}
					else {
						throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,
								"Cannot access indexed value of property referenced in indexed " +
										"property path '" + propertyName + "': returned null");
					}
				}
				StringBuilder indexedPropertyName = new StringBuilder(tokens.actualName);
				// apply indexes and map keys
				for (int i = 0; i < tokens.keys.length; i++) {
					String key = tokens.keys[i];

View on GitHub (pinned to e8729d0438)

Solutions

  1. Confirm a public getter exists for the property and that its name matches JavaBean conventions.
  2. Align the setter parameter type with the getter return type so the introspector treats the pair as consistent.
  3. Use wrapper.isReadableProperty(name) before calling getPropertyValue to avoid the exception.
  4. Correct the property name / check for typos.

Example fix

// before
public class Person { private String name; public void setName(String n) { this.name = n; } }
wrapper.getPropertyValue("name"); // no getter

// after
public String getName() { return name; }
Defensive patterns

Strategy: validation

Validate before calling

if (wrapper.isReadableProperty(propertyName)) {
    Object v = wrapper.getPropertyValue(propertyName);
}

Type guard

static boolean hasConsistentGetterSetter(Class<?> bean, String name) {
    try {
        java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
        for (java.beans.PropertyDescriptor pd : info.getPropertyDescriptors()) {
            if (pd.getName().equals(name)) {
                return pd.getReadMethod() != null
                    && (pd.getWriteMethod() == null
                        || pd.getWriteMethod().getParameterTypes()[0] == pd.getReadMethod().getReturnType());
            }
        }
        return false;
    } catch (Exception ex) { return false; }
}

Try / catch

try { Object v = wrapper.getPropertyValue(propertyName); }
catch (NotReadablePropertyException ex) { /* property has no usable getter */ }

Prevention

When it happens

Trigger: wrapper.getPropertyValue("foo") on a bean with no getFoo(); a bean where getFoo() returns String but setFoo(int) makes the pair inconsistent; accessing a write-only property for reading.

Common situations: Reading a property that only has a setter; model refactor renaming getters; binding/validation code that probes arbitrary property names; Kotlin data classes where a property is declared private.

Related errors


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