{"record":{"id":"e2a25f35944326cc","repo":"spring-projects/spring-framework","slug":"nested-property-in-path-propertyname-does-not","errorCode":null,"errorMessage":"Nested property in path '{propertyName}' does not exist","messagePattern":"Nested property in path '(.+?)' does not exist","errorType":"exception","errorClass":"NotWritablePropertyException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java","lineNumber":222,"sourceCode":"\t\treturn this.rootObject;\n\t}\n\n\t/**\n\t * Return the class of the root object at the top of the path of this accessor.\n\t * @see #getNestedPath\n\t */\n\tpublic final Class<?> getRootClass() {\n\t\treturn getRootInstance().getClass();\n\t}\n\n\t@Override\n\tpublic void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {\n\t\tAbstractNestablePropertyAccessor nestedPa;\n\t\ttry {\n\t\t\tnestedPa = getPropertyAccessorForPropertyPath(propertyName);\n\t\t}\n\t\tcatch (NotReadablePropertyException ex) {\n\t\t\tthrow new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,\n\t\t\t\t\t\"Nested property in path '\" + propertyName + \"' does not exist\", ex);\n\t\t}\n\t\tPropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));\n\t\tnestedPa.setPropertyValue(tokens, new PropertyValue(propertyName, value));\n\t}\n\n\t@Override\n\tpublic void setPropertyValue(PropertyValue pv) throws BeansException {\n\t\tPropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;\n\t\tif (tokens == null) {\n\t\t\tString propertyName = pv.getName();\n\t\t\tAbstractNestablePropertyAccessor nestedPa;\n\t\t\ttry {\n\t\t\t\tnestedPa = getPropertyAccessorForPropertyPath(propertyName);\n\t\t\t}\n\t\t\tcatch (NotReadablePropertyException ex) {\n\t\t\t\tthrow new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,\n\t\t\t\t\t\t\"Nested property in path '\" + propertyName + \"' does not exist\", ex);","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java#L204-L240","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nwrapper.setPropertyValue(\"custmer.address.city\", \"Berlin\"); // typo: custmer\n\n// after\nwrapper.setPropertyValue(\"customer.address.city\", \"Berlin\");","handlingStrategy":"validation","validationCode":"String path = \"customer.address.city\";\nBeanWrapper w = new BeanWrapperImpl(bean);\n// validate each intermediate segment is readable and the leaf is writable\nString[] parts = path.split(\"\\\\.\");\nStringBuilder cur = new StringBuilder();\nfor (int i = 0; i < parts.length; i++) {\n    cur.append(i == 0 ? \"\" : \".\").append(parts[i]);\n    if (i < parts.length - 1 && !w.isReadableProperty(cur.toString())) {\n        throw new IllegalArgumentException(\"path segment not readable: \" + cur);\n    }\n}\nif (!w.isWritableProperty(path)) {\n    throw new IllegalArgumentException(\"leaf not writable: \" + path);\n}\nw.setPropertyValue(path, value);","typeGuard":"static boolean pathLooksValid(BeanWrapper w, String path) {\n    String[] parts = path.split(\"\\\\.\");\n    StringBuilder cur = new StringBuilder();\n    for (int i = 0; i < parts.length; i++) {\n        cur.append(i == 0 ? \"\" : \".\").append(parts[i]);\n        if (i < parts.length - 1 && !w.isReadableProperty(cur.toString())) return false;\n    }\n    return w.isWritableProperty(path);\n}","tryCatchPattern":"try {\n    wrapper.setPropertyValue(\"a.b.c\", value);\n} catch (NotWritablePropertyException ex) {\n    // log and surface a binding error; check segment spelling / bean shape\n}","preventionTips":["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."],"tags":["spring-beans","bean-wrapper","nested-property","binding"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}