spring-projects/spring-framework · error · InvalidPropertyException

No property handler found

Error message

No property handler found

What it means

Thrown by processKeyedProperty when getLocalPropertyHandler(tokens.actualName) returns null for a property that is being addressed with a key/index (e.g. 'items[0]'). A keyed write needs a PropertyHandler to resolve element/key types and the setter; if no handler exists for the base property the framework cannot perform the indexed operation.

Solutions

  1. Confirm the base property (e.g. 'items') has a getter (and setter for writes) on the wrapped bean.
  2. Switch the accessor to direct field access (BeanWrapper / DirectFieldAccessor) if the value is a field with no accessor methods.
  3. If binding into a Map held by the bean, target the property name then the key: 'myMap[key]' where 'myMap' is a real property.
  4. Correct the property name spelling/case to match the bean.

Example fix

// before
wrapper.setPropertyValue("itemz[0]", x); // property is 'items', not 'itemz' -> No property handler found

// after
wrapper.setPropertyValue("items[0]", x);
Defensive patterns

Strategy: validation

Validate before calling

BeanWrapper w = new BeanWrapperImpl(bean);
String base = tokensBeforeIndex; // e.g. "items"
if (w.getPropertyType(base) == null) {
    throw new IllegalArgumentException("no property handler for " + base);
}
w.setPropertyValue(base + "[0]", value);

Type guard

static boolean hasPropertyHandler(BeanWrapper w, String base) {
    try { return w.getPropertyDescriptor(base) != null; }
    catch (InvalidPropertyException e) { return false; }
}

Try / catch

try {
    wrapper.setPropertyValue("items[0]", value);
} catch (InvalidPropertyException ex) {
    if (ex.getMessage().contains("No property handler")) { /* expose field-access or fix name */ }
    else throw ex;
}

Prevention

When it happens

Trigger: Calling setPropertyValue("items[0]", value) on a BeanWrapper where 'items' is not a recognized JavaBean property (no getter/setter and no field exposure) of the wrapped object.

Common situations: Binding to a public field directly with indexed syntax on a BeanWrapper that only honors getters/setters; misspelled collection property; wrapping a Map itself and using indexed syntax expecting map semantics on a non-property; using DirectFieldAccess that wasn't enabled so a field isn't seen as a property.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/d49c579e65673efc. Report an issue: GitHub.

Appendix: source

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

			setPropertyValue(tokens, pv);
		}
	}

	protected void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
		if (tokens.keys != null) {
			processKeyedProperty(tokens, pv);
		}
		else {
			processLocalProperty(tokens, pv);
		}
	}

	@SuppressWarnings({"rawtypes", "unchecked"})
	private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
		Object propValue = getPropertyHoldingValue(tokens);
		PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
		if (ph == null) {
			throw new InvalidPropertyException(
					getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
		}
		Assert.state(tokens.keys != null, "No token keys");
		String lastKey = tokens.keys[tokens.keys.length - 1];

		if (propValue.getClass().isArray()) {
			Class<?> componentType = propValue.getClass().componentType();
			int arrayIndex = Integer.parseInt(lastKey);
			Object oldValue = null;
			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);

View on GitHub (pinned to 69bf83ad71)