{"id":"b2d3c4ecf5852483","repo":"spring-projects/spring-framework","slug":"invalid-list-index-in-property-path-tokens-canon","errorCode":null,"errorMessage":"Invalid list index in property path '{tokens.canonicalName}'","messagePattern":"Invalid list index in property path '(.+?)'","errorType":"exception","errorClass":"InvalidPropertyException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java","lineNumber":329,"sourceCode":"\t\t\t\tfor (int i = size; i < index; i++) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlist.add(null);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (NullPointerException ex) {\n\t\t\t\t\t\tthrow new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,\n\t\t\t\t\t\t\t\t\"Cannot set element with index \" + index + \" in List of size \" +\n\t\t\t\t\t\t\t\tsize + \", accessed using property path '\" + tokens.canonicalName +\n\t\t\t\t\t\t\t\t\"': List does not support filling up gaps with null elements\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlist.add(convertedValue);\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttry {\n\t\t\t\t\tlist.set(index, convertedValue);\n\t\t\t\t}\n\t\t\t\tcatch (IndexOutOfBoundsException ex) {\n\t\t\t\t\tthrow new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,\n\t\t\t\t\t\t\t\"Invalid list index in property path '\" + tokens.canonicalName + \"'\", ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\telse if (propValue instanceof Map map) {\n\t\t\tTypeDescriptor mapKeyType = ph.getMapKeyType(tokens.keys.length);\n\t\t\tTypeDescriptor mapValueType = ph.getMapValueType(tokens.keys.length);\n\t\t\t// IMPORTANT: Do not pass full property name in here - property editors\n\t\t\t// must not kick in for map keys but rather only for map values.\n\t\t\tObject convertedMapKey = convertIfNecessary(null, null, lastKey,\n\t\t\t\t\tmapKeyType.getResolvableType().resolve(), mapKeyType);\n\t\t\tObject oldValue = null;\n\t\t\tif (isExtractOldValueForEditor()) {\n\t\t\t\toldValue = map.get(convertedMapKey);\n\t\t\t}\n\t\t\t// Pass full property name and old value in here, since we want full\n\t\t\t// conversion ability for map values.","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java#L311-L347","documentation":"Thrown in the List branch of processKeyedProperty when the index is in range that does not trigger auto-grow (index < size expected) and list.set(index, convertedValue) throws IndexOutOfBoundsException. Spring rewraps it as InvalidPropertyException 'Invalid list index'. This is the non-auto-grow / contiguous-range failure for indexed List writes.","triggerScenarios":"setProperty(\"items[7]\", x) on an ArrayList of size 3 with autoGrowNestedPaths=false; index beyond the list size but auto-grow off; binding to a list that was not pre-sized.","commonSituations":"autoGrowNestedPaths disabled by default in custom BeanWrapper usage; binding positional data into a List without pre-filling; converting from array semantics where auto-grow was expected but not enabled.","solutions":["Enable wrapper.setAutoGrowNestedPaths(true) so the list grows up to the auto-grow limit.","Pre-fill the list so the target index already exists before binding.","Use contiguous indices starting at 0 when binding sequentially.","Switch to add-style binding via a non-indexed property if order is not significant."],"exampleFix":"// before\nList<Item> items = new ArrayList<>(); // size 0\nwrapper.setPropertyValue(\"items[2]\", item); // autoGrow off -> OOB\n\n// after\nwrapper.setAutoGrowNestedPaths(true);\nwrapper.setPropertyValue(\"items[2]\", item);","handlingStrategy":"validation","validationCode":"int idx = 7;\nList<Object> list = (List<Object>) wrapper.getPropertyValue(\"items\");\nif (list == null) { list = new ArrayList<>(); wrapper.setPropertyValue(\"items\", list); }\nwhile (list.size() <= idx) list.add(null);\nwrapper.setPropertyValue(\"items[\" + idx + \"]\", item);","typeGuard":"static boolean indexExistsOrGrow(List<?> list, BeanWrapper bw, int idx) {\n    return idx < list.size() || (bw.isAutoGrowNestedPaths() && idx < bw.getAutoGrowCollectionLimit());\n}","tryCatchPattern":"try { wrapper.setPropertyValue(\"items[\" + idx + \"]\", item); }\ncatch (InvalidPropertyException ex) { /* pre-fill list then retry */ }","preventionTips":["Enable autoGrowNestedPaths for tolerant indexed writes.","Pre-fill lists to the required size before binding.","Use contiguous indices when binding sequentially."],"tags":["spring-beans","bean-wrapper","list","indexed-property","index-out-of-bounds"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}