spring-projects/spring-framework · error · InvalidPropertyException

Invalid array index in property path '{tokens.canonicalName}

Error message

Invalid array index in property path '{tokens.canonicalName}'

What it means

Raised in the array branch of processKeyedProperty when Array.set(array, arrayIndex, value) throws IndexOutOfBoundsException. Auto-grow only expands the array when arrayIndex < getAutoGrowCollectionLimit(); beyond that limit (or when auto-grow is off) the raw Array.set fails and Spring rewraps it as InvalidPropertyException 'Invalid array index'. The index in the message is the one in the canonical path like 'items[123]'.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java:295

			try {
				if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
					oldValue = Array.get(propValue, arrayIndex);
				}
				Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
						componentType, ph.nested(tokens.keys.length));
				int length = Array.getLength(propValue);
				if (arrayIndex >= length && arrayIndex < getAutoGrowCollectionLimit()) {
					Object newArray = Array.newInstance(componentType, arrayIndex + 1);
					System.arraycopy(propValue, 0, newArray, 0, length);
					int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
					String propName = tokens.canonicalName.substring(0, lastKeyIndex);
					setPropertyValue(propName, newArray);
					propValue = getPropertyValue(propName);
				}
				Array.set(propValue, arrayIndex, convertedValue);
			}
			catch (IndexOutOfBoundsException ex) {
				throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
						"Invalid array index in property path '" + tokens.canonicalName + "'", ex);
			}
		}

		else if (propValue instanceof List list) {
			TypeDescriptor requiredType = ph.getCollectionType(tokens.keys.length);
			int index = Integer.parseInt(lastKey);
			Object oldValue = null;
			if (isExtractOldValueForEditor() && index < list.size()) {
				oldValue = list.get(index);
			}
			Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
					requiredType.getResolvableType().resolve(), requiredType);
			int size = list.size();
			if (index >= size && index < getAutoGrowCollectionLimit()) {
				for (int i = size; i < index; i++) {
					try {
						list.add(null);

View on GitHub (pinned to e8729d0438)

Solutions

  1. Increase setAutoGrowCollectionLimit above the largest index you bind.
  2. Pre-size the target array to fit the index before binding.
  3. Prefer a List over an array if indices vary widely, so auto-grow can append.
  4. Switch from indexed array writes to fully replacing the array.

Example fix

// before
wrapper.setAutoGrowCollectionLimit(128);
wrapper.setPropertyValue("slots[200]", true); // 200 > 128

// after
wrapper.setAutoGrowCollectionLimit(256);
wrapper.setPropertyValue("slots[200]", true);
Defensive patterns

Strategy: validation

Validate before calling

int idx = 200;
if (wrapper.isAutoGrowNestedPaths() && idx < wrapper.getAutoGrowCollectionLimit()) {
    wrapper.setPropertyValue("slots[" + idx + "]", true);
} else if (Array.getLength(wrapper.getPropertyValue("slots")) > idx) {
    wrapper.setPropertyValue("slots[" + idx + "]", true);
} else throw new IllegalArgumentException("index too large");

Type guard

static boolean indexWithinArrayOrGrowLimit(BeanWrapper bw, Object array, int idx) {
    return Array.getLength(array) > idx || (bw.isAutoGrowNestedPaths() && idx < bw.getAutoGrowCollectionLimit());
}

Try / catch

try { wrapper.setPropertyValue("slots[" + idx + "]", v); }
catch (InvalidPropertyException ex) { /* resize array manually, retry */ }

Prevention

When it happens

Trigger: setProperty("arr[150]", x) on an array of length 10 with autoGrowCollectionLimit at its default of 128 (150 > 128 so no auto-grow); writing to an array index that does not exist and autoGrowNestedPaths is false; binding to an array-backed field where the incoming index exceeds both the array length and the auto-grow ceiling.

Common situations: Bounded auto-grow limit (default 128) being exceeded by large indices; binding spreadsheet/CSV row data to arrays; disabling autoGrowNestedPaths while still using indexed writes.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/102f3f60d4975869.json. Report an issue: GitHub.