{"id":"d37d7d34d540c3e4","repo":"spring-projects/spring-framework","slug":"value-of-nested-property-nestedpath-canonical","errorCode":null,"errorMessage":"Value of nested property '${nestedPath}${canonicalName}' is null","messagePattern":"Value of nested property '(.+?)(.+?)' is null","errorType":"exception","errorClass":"NullValueInNestedPathException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java","lineNumber":836,"sourceCode":"\t * @param nestedProperty property to create the PropertyAccessor for\n\t * @return the PropertyAccessor instance, either cached or newly created\n\t */\n\tprivate AbstractNestablePropertyAccessor getNestedPropertyAccessor(String nestedProperty) {\n\t\tMap<String, AbstractNestablePropertyAccessor> nestedAccessors = this.nestedPropertyAccessors;\n\t\tif (nestedAccessors == null) {\n\t\t\tnestedAccessors = new HashMap<>();\n\t\t\tthis.nestedPropertyAccessors = nestedAccessors;\n\t\t}\n\t\t// Get value of bean property.\n\t\tPropertyTokenHolder tokens = getPropertyNameTokens(nestedProperty);\n\t\tString canonicalName = tokens.canonicalName;\n\t\tObject value = getPropertyValue(tokens);\n\t\tif (value == null || (value instanceof Optional<?> optional && optional.isEmpty())) {\n\t\t\tif (isAutoGrowNestedPaths()) {\n\t\t\t\tvalue = setDefaultValue(tokens);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new NullValueInNestedPathException(getRootClass(), this.nestedPath + canonicalName);\n\t\t\t}\n\t\t}\n\n\t\t// Lookup cached sub-PropertyAccessor, create new one if not found.\n\t\tAbstractNestablePropertyAccessor nestedPa = nestedAccessors.get(canonicalName);\n\t\tif (nestedPa == null || nestedPa.getWrappedInstance() != ObjectUtils.unwrapOptional(value)) {\n\t\t\tif (logger.isTraceEnabled()) {\n\t\t\t\tlogger.trace(\"Creating new nested \" + getClass().getSimpleName() + \" for property '\" + canonicalName + \"'\");\n\t\t\t}\n\t\t\tnestedPa = newNestedPropertyAccessor(value, this.nestedPath + canonicalName + NESTED_PROPERTY_SEPARATOR);\n\t\t\t// Inherit all type-specific PropertyEditors.\n\t\t\tcopyDefaultEditorsTo(nestedPa);\n\t\t\tcopyCustomEditorsTo(nestedPa, canonicalName);\n\t\t\tnestedAccessors.put(canonicalName, nestedPa);\n\t\t}\n\t\telse {\n\t\t\tif (logger.isTraceEnabled()) {\n\t\t\t\tlogger.trace(\"Using cached nested property accessor for property '\" + canonicalName + \"'\");","sourceCodeStart":818,"sourceCodeEnd":854,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java#L818-L854","documentation":"Thrown as NullValueInNestedPathException by AbstractNestablePropertyAccessor when resolving a nested property path (e.g. 'address.city') and an intermediate segment is null while auto-grow-nested-paths is disabled. Spring refuses to silently descend into null because it cannot obtain a BeanWrapper for the missing intermediate bean. The path string in the message is the accumulated nested path plus the canonical property name.","triggerScenarios":"Calling BeanWrapperImpl.setPropertyValue('a.b.c', val) / DataBinder binding when the target's 'a' (or 'a.b') field is null and wrapper.setAutoGrowNestedPaths(false) (the default). Also triggered by getNestedPropertyAccessor when reading a nested path whose value is null or an empty Optional.","commonSituations":"Binding a form-backing bean where the nested object was never initialized (e.g. new Order() with a null Address). YAML/properties binding into a graph that has null intermediate references. Spring MVC form binding to a command object whose nested entity field is null.","solutions":["Initialize the nested property in the target class (e.g. private Address address = new Address();) so the path is never null.","Enable auto-grow: wrapper.setAutoGrowNestedPaths(true) or set 'spring.databinding.auto-grow-nested-paths=true' where supported, so Spring creates intermediate instances.","Bind a non-null instance before setting nested values, or restructure the bean so the intermediate is set at construction.","Catch NullValueInNestedPathException around binding and report a user-facing validation error instead of propagating."],"exampleFix":"// before\nOrder order = new Order(); // order.address == null\nBeanWrapper w = new BeanWrapperImpl(order);\nw.setPropertyValue(\"address.city\", \"NYC\"); // -> NullValueInNestedPathException\n\n// after (initialize nested bean)\npublic class Order { private Address address = new Address(); }\n// or: w.setAutoGrowNestedPaths(true);","handlingStrategy":"validation","validationCode":"// Before binding a nested path, ensure intermediates are non-null\npublic static void ensurePath(Object root, String... props) throws Exception {\n  Object cur = root;\n  StringBuilder path = new StringBuilder();\n  for (String p : props) {\n    path.append(p).append('.');\n    PropertyDescriptor pd = Arrays.stream(\n        Introspector.getBeanInfo(cur.getClass()).getPropertyDescriptors())\n        .filter(d -> d.getName().equals(p)).findFirst().orElseThrow();\n    Object next = pd.getReadMethod().invoke(cur);\n    if (next == null) {\n      Object made = pd.getPropertyType().getDeclaredConstructor().newInstance();\n      pd.getWriteMethod().invoke(cur, made);\n      next = made;\n    }\n    cur = next;\n  }\n}","typeGuard":"public static boolean isNestedPathResolvable(BeanWrapper w, String path) {\n  try { return w.getPropertyValue(path) != null || w.isAutoGrowNestedPaths(); }\n  catch (NullValueInNestedPathException e) { return false; }\n}","tryCatchPattern":"try {\n  wrapper.setPropertyValue(\"address.city\", value);\n} catch (NullValueInNestedPathException e) {\n  // surface as a binding/validation error: \"missing intermediate for \" + e.getPropertyName()\n}","preventionTips":["Initialize nested fields at declaration (private Address address = new Address();).","Enable setAutoGrowNestedPaths(true) when binding dynamic graphs.","Validate the command bean's nested fields are non-null in an @InitBinder or validator."],"tags":["spring-beans","bean-wrapper","nested-property","binding","null-value"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}