spring-projects/spring-framework · error · InvalidPropertyException

Property referenced in indexed property path '{tokens.canoni

Error message

Property referenced in indexed property path '{tokens.canonicalName}' is neither an array nor a List nor a Map; returned value was [{propValue}]

What it means

Thrown in the final else of processKeyedProperty: the property path uses index/map syntax (e.g. 'foo[0]' or 'foo[key]') but the resolved value is not an array, List, or Map. Because there is no keyed access possible, Spring raises InvalidPropertyException naming the canonical path and showing the offending value.

Source

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

			TypeDescriptor mapKeyType = ph.getMapKeyType(tokens.keys.length);
			TypeDescriptor mapValueType = ph.getMapValueType(tokens.keys.length);
			// IMPORTANT: Do not pass full property name in here - property editors
			// must not kick in for map keys but rather only for map values.
			Object convertedMapKey = convertIfNecessary(null, null, lastKey,
					mapKeyType.getResolvableType().resolve(), mapKeyType);
			Object oldValue = null;
			if (isExtractOldValueForEditor()) {
				oldValue = map.get(convertedMapKey);
			}
			// Pass full property name and old value in here, since we want full
			// conversion ability for map values.
			Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
					mapValueType.getResolvableType().resolve(), mapValueType);
			map.put(convertedMapKey, convertedMapValue);
		}

		else {
			throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
					"Property referenced in indexed property path '" + tokens.canonicalName +
					"' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
		}
	}

	private Object getPropertyHoldingValue(PropertyTokenHolder tokens) {
		// Apply indexes and map keys: fetch value for all keys but the last one.
		Assert.state(tokens.keys != null, "No token keys");
		PropertyTokenHolder getterTokens = new PropertyTokenHolder(tokens.actualName);
		getterTokens.canonicalName = tokens.canonicalName;
		getterTokens.keys = new String[tokens.keys.length - 1];
		System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);

		Object propValue;
		try {
			propValue = getPropertyValue(getterTokens);
		}
		catch (NotReadablePropertyException ex) {

View on GitHub (pinned to e8729d0438)

Solutions

  1. Change the bean property to an array, List, or Map so indexed/mapped writes are valid.
  2. Remove the index/bracket from the path if the target is genuinely scalar.
  3. Re-check the path spelling and ensure the intended collection property is being addressed.

Example fix

// before
public class Cart { private int itemCount; ... }
wrapper.setPropertyValue("itemCount[0]", 1); // scalar, not indexable

// after
public class Cart { private List<Integer> itemCounts = new ArrayList<>(); ... }
wrapper.setPropertyValue("itemCounts[0]", 1);
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> type = wrapper.getPropertyType("count");
if (type != null && (type.isArray() || List.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type))) {
    wrapper.setPropertyValue("count[0]", value);
}

Type guard

static boolean isIndexable(Class<?> type) {
    return type != null && (type.isArray() || List.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type));
}

Try / catch

try { wrapper.setPropertyValue(path, value); }
catch (InvalidPropertyException ex) { /* property is scalar; drop bracket */ }

Prevention

When it happens

Trigger: setProperty("count[0]", x) where getCount() returns an int; binding 'name[key]' onto a String property; a path where the collection field was replaced by a scalar type in a refactor.

Common situations: Binding indexed form fields onto a bean whose property is a scalar after a model change; SpEL/BeanWrapper misuse applying brackets to non-collection fields; misconfigured @ConfigurationProperties mapping a list key onto a single-value field.

Related errors


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