spring-projects/spring-framework · error · InvalidPropertyException

Invalid property '{propertyName}' of bean class [{beanClass.

Error message

Invalid property '{propertyName}' of bean class [{beanClass.getName()}]: Invalid index in property path '{propertyName}'

What it means

Thrown by getPropertyValue when applying a key throws NumberFormatException (the index token is not an integer on an array/List) or TypeMismatchException (key cannot be coerced to the map key type). Wrapped as InvalidPropertyException so the binding layer surfaces a consistent property error.

Source

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

						throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
								"Property referenced in indexed property path '" + propertyName +
										"' is neither an array nor a List/Set/Collection/Iterable nor a Map; " +
										"returned value was [" + value + "]");
					}
					indexedPropertyName.append(PROPERTY_KEY_PREFIX).append(key).append(PROPERTY_KEY_SUFFIX);
				}
			}
			return value;
		}
		catch (InvalidPropertyException ex) {
			throw ex;
		}
		catch (IndexOutOfBoundsException ex) {
			throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
					"Index of out of bounds in property path '" + propertyName + "'", ex);
		}
		catch (NumberFormatException | TypeMismatchException ex) {
			throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
					"Invalid index in property path '" + propertyName + "'", ex);
		}
		catch (InvocationTargetException ex) {
			throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
					"Getter for property '" + actualName + "' threw exception", ex);
		}
		catch (Exception ex) {
			throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
					"Illegal attempt to get property '" + actualName + "' threw exception", ex);
		}
	}


	/**
	 * Return the {@link PropertyHandler} for the specified {@code propertyName}, navigating
	 * if necessary. Return {@code null} if not found rather than throwing an exception.
	 * @param propertyName the property to obtain the descriptor for
	 * @return the property descriptor for the specified property,

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Validate that index tokens are integers before applying them to array/List properties.
  2. Register a Converter<String, KeyType> (or use ConversionService) so map keys coerce correctly.
  3. Align the map key generic type with the values you bind (e.g. Map<String,?> for string keys).
  4. Sanitize/escape property paths constructed from user input.

Example fix

// before
// Map<Integer,String> ids;
wrapper.getPropertyValue("ids[abc]"); // not an Integer

// after
// Map<String,String> ids;
wrapper.getPropertyValue("ids[abc]");
// or register Converter<String,Integer>
Defensive patterns

Strategy: validation

Validate before calling

BeanWrapper w = new BeanWrapperImpl(bean);
Class<?> type = w.getPropertyType("ids");
if (type != null && type.isArray()) {
    Integer.parseInt(indexToken); // ensure numeric for array/list
} else if (Map.class.isAssignableFrom(type)) {
    // ensure a converter exists for the key type, or pre-coerce
    TypeDescriptor td = w.getPropertyTypeDescriptor("ids");
    Class<?> keyType = td.getMapKeyTypeDescriptor().getType();
    conversionService.convert(indexToken, keyType);
}
return w.getPropertyValue("ids[" + indexToken + "]");

Type guard

static boolean indexTokenValidFor(Class<?> containerType, String token) {
    if (containerType == null) return false;
    if (containerType.isArray() || List.class.isAssignableFrom(containerType)) {
        try { Integer.parseInt(token); return true; } catch (NumberFormatException e) { return false; }
    }
    return Map.class.isAssignableFrom(containerType); // any string is acceptable pending converter
}

Try / catch

try {
    return wrapper.getPropertyValue(path);
} catch (InvalidPropertyException ex) {
    if (ex.getCause() instanceof NumberFormatException || ex.getCause() instanceof TypeMismatchException) {
        // index not coercible; surface a binding error
    } else throw ex;
}

Prevention

When it happens

Trigger: getPropertyValue("arr[abc]") on an array/List (non-numeric index); getPropertyValue("map[key]") where 'key' cannot be converted to the Map's declared key type (e.g. Map<Integer,?> and key="abc").

Common situations: User-supplied property path with a non-numeric index on a sequence; binding a String key onto a numeric-keyed Map without a registered Converter; mismatched map key generic types after a refactor.

Related errors


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