{"record":{"id":"102f3f60d4975869","repo":"spring-projects/spring-framework","slug":"invalid-array-index-in-property-path-tokens-cano","errorCode":null,"errorMessage":"Invalid array index in property path '{tokens.canonicalName}'","messagePattern":"Invalid array index in property path '(.+?)'","errorType":"exception","errorClass":"InvalidPropertyException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java","lineNumber":295,"sourceCode":"\t\t\ttry {\n\t\t\t\tif (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {\n\t\t\t\t\toldValue = Array.get(propValue, arrayIndex);\n\t\t\t\t}\n\t\t\t\tObject convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),\n\t\t\t\t\t\tcomponentType, ph.nested(tokens.keys.length));\n\t\t\t\tint length = Array.getLength(propValue);\n\t\t\t\tif (arrayIndex >= length && arrayIndex < getAutoGrowCollectionLimit()) {\n\t\t\t\t\tObject newArray = Array.newInstance(componentType, arrayIndex + 1);\n\t\t\t\t\tSystem.arraycopy(propValue, 0, newArray, 0, length);\n\t\t\t\t\tint lastKeyIndex = tokens.canonicalName.lastIndexOf('[');\n\t\t\t\t\tString propName = tokens.canonicalName.substring(0, lastKeyIndex);\n\t\t\t\t\tsetPropertyValue(propName, newArray);\n\t\t\t\t\tpropValue = getPropertyValue(propName);\n\t\t\t\t}\n\t\t\t\tArray.set(propValue, arrayIndex, convertedValue);\n\t\t\t}\n\t\t\tcatch (IndexOutOfBoundsException ex) {\n\t\t\t\tthrow new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,\n\t\t\t\t\t\t\"Invalid array index in property path '\" + tokens.canonicalName + \"'\", ex);\n\t\t\t}\n\t\t}\n\n\t\telse if (propValue instanceof List list) {\n\t\t\tTypeDescriptor requiredType = ph.getCollectionType(tokens.keys.length);\n\t\t\tint index = Integer.parseInt(lastKey);\n\t\t\tObject oldValue = null;\n\t\t\tif (isExtractOldValueForEditor() && index < list.size()) {\n\t\t\t\toldValue = list.get(index);\n\t\t\t}\n\t\t\tObject convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),\n\t\t\t\t\trequiredType.getResolvableType().resolve(), requiredType);\n\t\t\tint size = list.size();\n\t\t\tif (index >= size && index < getAutoGrowCollectionLimit()) {\n\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);","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java#L277-L313","documentation":"Thrown by processKeyedProperty in the array branch when Array.set throws IndexOutOfBoundsException. Spring will auto-grow the array up to getAutoGrowCollectionLimit() (default 256); beyond that, or when autoGrow is disabled, the out-of-bounds is wrapped as InvalidPropertyException.","triggerScenarios":"setProperty(\"arr[3000]\", value) with default autoGrowCollectionLimit=256; or autoGrowNestedPaths=false and arr.length <= index.","commonSituations":"Form binding array-indexed fields with sparse/large indices; autoGrow disabled explicitly; autoGrowCollectionLimit lowered; client sending an out-of-range index.","solutions":["Pre-size / pre-allocate the target array so the index is in range.","Enable autoGrowNestedPaths and raise setAutoGrowCollectionLimit if the index is legitimate (mind memory).","Validate the incoming index on the controller/binder side and reject values beyond the array bounds.","Switch from an array to a List/Map if indices are sparse or arbitrary."],"exampleFix":"// before\nwrapper.setAutoGrowNestedPaths(false);\nwrapper.setPropertyValue(\"arr[5]\", v); // arr.length == 0\n\n// after\nwrapper.setAutoGrowNestedPaths(true);\nwrapper.setAutoGrowCollectionLimit(64);\nwrapper.setPropertyValue(\"arr[5]\", v);","handlingStrategy":"validation","validationCode":"BeanWrapper w = new BeanWrapperImpl(bean);\nString base = \"arr\"; int idx = requestedIndex;\nObject arr = w.getPropertyValue(base);\nint len = arr == null ? 0 : java.lang.reflect.Array.getLength(arr);\nif (idx < 0 || idx >= len) {\n    w.setAutoGrowNestedPaths(true);\n    w.setAutoGrowCollectionLimit(Math.max(w.getAutoGrowCollectionLimit(), idx + 1));\n}\nw.setPropertyValue(base + \"[\" + idx + \"]\", value);","typeGuard":"static boolean inArrayBounds(Object array, int idx) {\n    return array != null && array.getClass().isArray() && idx >= 0 && idx < java.lang.reflect.Array.getLength(array);\n}","tryCatchPattern":"try {\n    wrapper.setPropertyValue(\"arr[\" + idx + \"]\", v);\n} catch (InvalidPropertyException ex) {\n    if (ex.getCause() instanceof IndexOutOfBoundsException) { /* pre-size array or raise 400 */ }\n    else throw ex;\n}","preventionTips":["Pre-size arrays to the max expected index.","Set a sensible autoGrowCollectionLimit; reject indices beyond it at the controller.","Prefer List/Map over arrays for user-driven indices."],"tags":["spring-beans","bean-wrapper","array","index-out-of-bounds","autogrow"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}