spring-projects/spring-framework · error · NotWritablePropertyException
Nested property in path
Error message
Nested property in path '{propertyName}' does not exist What it means
Thrown by setPropertyValue(String, Object) when navigating a nested property path (e.g. 'a.b.c') raises a NotReadablePropertyException on an intermediate segment. It is rethrown as a NotWritablePropertyException with this message, signalling that a parent property in the write path does not exist (so the leaf cannot be written).
Solutions
- Verify each path segment exists (has a readable getter) on the wrapped class; check spelling/case.
- Use beanWrapper.isReadableProperty("customer.address") and isWritableProperty("customer.address.city") before setting.
- Enable autoGrowNestedPaths (setAutoGrowNestedPaths(true)) if intermediate segments legitimately start null but have typed getters.
- If the type was refactored, update the property path / binding source to match the new bean shape.
Example fix
// before
wrapper.setPropertyValue("custmer.address.city", "Berlin"); // typo: custmer
// after
wrapper.setPropertyValue("customer.address.city", "Berlin"); Defensive patterns
Strategy: validation
Validate before calling
String path = "customer.address.city";
BeanWrapper w = new BeanWrapperImpl(bean);
// validate each intermediate segment is readable and the leaf is writable
String[] parts = path.split("\\.");
StringBuilder cur = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
cur.append(i == 0 ? "" : ".").append(parts[i]);
if (i < parts.length - 1 && !w.isReadableProperty(cur.toString())) {
throw new IllegalArgumentException("path segment not readable: " + cur);
}
}
if (!w.isWritableProperty(path)) {
throw new IllegalArgumentException("leaf not writable: " + path);
}
w.setPropertyValue(path, value); Type guard
static boolean pathLooksValid(BeanWrapper w, String path) {
String[] parts = path.split("\\.");
StringBuilder cur = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
cur.append(i == 0 ? "" : ".").append(parts[i]);
if (i < parts.length - 1 && !w.isReadableProperty(cur.toString())) return false;
}
return w.isWritableProperty(path);
} Try / catch
try {
wrapper.setPropertyValue("a.b.c", value);
} catch (NotWritablePropertyException ex) {
// log and surface a binding error; check segment spelling / bean shape
} Prevention
- Keep property paths and bean shapes in lockstep; update binding config when refactoring.
- Unit-test binding of every nested path against the current class.
- Enable autoGrowNestedPaths only when intermediate segments may be null but are typed.
When it happens
Trigger: Calling beanWrapper.setPropertyValue("customer.address.city", value) when 'address' (or 'customer') has no getter/field on the target bean, so getPropertyAccessorForPropertyPath fails to resolve the path.
Common situations: Typo in a nested property name in XML/YAML/SpEL binding; renaming a bean property and forgetting to update binding configuration; binding against the wrong bean class; accessing a property that exists on a subtype after the wrapper was created on the supertype.
Related errors
- Cannot access indexed value in property referenced in…
- Invalid property ' ' of bean class [ ]
- Cannot access indexed value in property referenced in…
- Cannot access indexed value of property referenced in…
- Cannot get element with index
AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09).
Data as JSON: /api/errors/e2a25f35944326cc.
Report an issue: GitHub.
Appendix: source
Thrown at spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java:222
return this.rootObject;
}
/**
* Return the class of the root object at the top of the path of this accessor.
* @see #getNestedPath
*/
public final Class<?> getRootClass() {
return getRootInstance().getClass();
}
@Override
public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);
}
PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
nestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value));
}
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
if (tokens == null) {
String propertyName = pv.getName();
AbstractNestablePropertyAccessor nestedPa;
try {
nestedPa = getPropertyAccessorForPropertyPath(propertyName);
}
catch (NotReadablePropertyException ex) {
throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
"Nested property in path '" + propertyName + "' does not exist", ex);View on GitHub (pinned to 69bf83ad71)