{"id":"00a805874259acde","repo":"spring-projects/spring-framework","slug":"could-not-determine-property-type-for-auto-growing","errorCode":null,"errorMessage":"Could not determine property type for auto-growing a default value","messagePattern":"Could not determine property type for auto-growing a default value","errorType":"exception","errorClass":"NullValueInNestedPathException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java","lineNumber":871,"sourceCode":"\t\t\tif (logger.isTraceEnabled()) {\n\t\t\t\tlogger.trace(\"Using cached nested property accessor for property '\" + canonicalName + \"'\");\n\t\t\t}\n\t\t}\n\t\treturn nestedPa;\n\t}\n\n\tprivate Object setDefaultValue(PropertyTokenHolder tokens) {\n\t\tPropertyValue pv = createDefaultPropertyValue(tokens);\n\t\tsetPropertyValue(tokens, pv);\n\t\tObject defaultValue = getPropertyValue(tokens);\n\t\tAssert.state(defaultValue != null, \"Default value must not be null\");\n\t\treturn defaultValue;\n\t}\n\n\tprivate PropertyValue createDefaultPropertyValue(PropertyTokenHolder tokens) {\n\t\tTypeDescriptor desc = getPropertyTypeDescriptor(tokens.canonicalName);\n\t\tif (desc == null) {\n\t\t\tthrow new NullValueInNestedPathException(getRootClass(), this.nestedPath + tokens.canonicalName,\n\t\t\t\t\t\"Could not determine property type for auto-growing a default value\");\n\t\t}\n\t\tObject defaultValue = newValue(desc.getType(), desc, tokens.canonicalName);\n\t\treturn new PropertyValue(tokens.canonicalName, defaultValue);\n\t}\n\n\tprivate Object newValue(Class<?> type, @Nullable TypeDescriptor desc, String name) {\n\t\ttry {\n\t\t\tif (type.isArray()) {\n\t\t\t\treturn createArray(type);\n\t\t\t}\n\t\t\telse if (Collection.class.isAssignableFrom(type)) {\n\t\t\t\tTypeDescriptor elementDesc = (desc != null ? desc.getElementTypeDescriptor() : null);\n\t\t\t\treturn CollectionFactory.createCollection(type, (elementDesc != null ? elementDesc.getType() : null), 16);\n\t\t\t}\n\t\t\telse if (Map.class.isAssignableFrom(type)) {\n\t\t\t\tTypeDescriptor keyDesc = (desc != null ? desc.getMapKeyTypeDescriptor() : null);\n\t\t\t\treturn CollectionFactory.createMap(type, (keyDesc != null ? keyDesc.getType() : null), 16);","sourceCodeStart":853,"sourceCodeEnd":889,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java#L853-L889","documentation":"Thrown as NullValueInNestedPathException during auto-growing when getPropertyTypeDescriptor(canonicalName) returns null, meaning Spring cannot determine the Java type to instantiate for the missing nested segment. Without a type, newValue(...) cannot create a default, so the auto-grow attempt fails even though auto-grow is enabled.","triggerScenarios":"autoGrowNestedPaths=true and binding into a property whose type is unresolvable: a raw-typed field, an unparameterized Object/Map element, a property with no read/write accessor, or a property name not present on the target class. Occurs inside createDefaultPropertyValue at AbstractNestablePropertyAccessor.java:868-873.","commonSituations":"Binding into Map<String,Object>-style loosely typed targets. Properties files / YAML mapping to a field whose getter/setter was removed or renamed. Generic base classes where erasure leaves the element type unknown. Typos in the property path that don't match any descriptor.","solutions":["Add a concrete field type and matching getter/setter so a TypeDescriptor is available (e.g. private Address address; with getAddress/setAddress).","Verify the property path spelling matches a real, introspectable bean property.","Disable autoGrowNestedPaths and instead pre-initialize the nested object, so the type-descriptor path is never taken.","Parameterize generic collections/maps explicitly (List<Address> not List) so element types resolve."],"exampleFix":"// before\npublic class Order { private Object address; } // type unknowable\nBeanWrapper w = new BeanWrapperImpl(order);\nw.setAutoGrowNestedPaths(true);\nw.setPropertyValue(\"address.city\", \"NYC\"); // type descriptor null\n\n// after\npublic class Order { private Address address; // + getter/setter }","handlingStrategy":"validation","validationCode":"// Confirm a TypeDescriptor is resolvable before relying on auto-grow\nBeanWrapper w = new BeanWrapperImpl(target);\nw.setAutoGrowNestedPaths(true);\nTypeDescriptor td = null;\ntry { td = ((AbstractNestablePropertyAccessor) w).getPropertyTypeDescriptor(propName); }\ncatch (Exception ignored) {}\nif (td == null) { /* do not auto-grow; initialize manually */ }","typeGuard":"public static boolean hasResolvableTypeDescriptor(BeanWrapper w, String prop) {\n  try { return w.getPropertyTypeDescriptor(prop) != null; }\n  catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n  wrapper.setAutoGrowNestedPaths(true);\n  wrapper.setPropertyValue(path, value);\n} catch (NullValueInNestedPathException e) {\n  if (e.getMessage().contains(\"auto-growing\")) { /* initialize nested field manually */ }\n}","preventionTips":["Declare concrete field types with getters/setters so descriptors resolve.","Parameterize generics (List<Address> not raw List).","Prefer pre-initialized nested objects over auto-grow for loosely-typed targets."],"tags":["spring-beans","bean-wrapper","auto-grow","type-descriptor","binding"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}