spring-projects/spring-framework · error · IntrospectionException
Type mismatch between indexed and non-indexed methods: ${ind
Error message
Type mismatch between indexed and non-indexed methods: ${indexedReadMethod} - ${indexedWriteMethod} What it means
IntrospectionException from PropertyDescriptorUtils.findIndexedPropertyType when a non-indexed property type is supplied alongside indexed accessors and they disagree. Specifically: the non-indexed propertyType exists, is not an array, OR is an array but its component type differs from the indexed element type. The JavaBean model expects an indexed property to be backed by an array-typed simple property of the same component type.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java:239
// Write method's property type potentially more specific
indexedPropertyType = params[1];
}
else if (params[1].isAssignableFrom(indexedPropertyType)) {
// Proceed with read method's property type
}
else {
throw new IntrospectionException("Type mismatch between indexed read and write methods: " +
indexedReadMethod + " - " + indexedWriteMethod);
}
}
else {
indexedPropertyType = params[1];
}
}
if (propertyType != null && (!propertyType.isArray() ||
propertyType.componentType() != indexedPropertyType)) {
throw new IntrospectionException("Type mismatch between indexed and non-indexed methods: " +
indexedReadMethod + " - " + indexedWriteMethod);
}
return indexedPropertyType;
}
/**
* Compare the given {@code PropertyDescriptors} and return {@code true} if
* they are equivalent, i.e. their read method, write method, property type,
* property editor and flags are equivalent.
* @see java.beans.PropertyDescriptor#equals(Object)
*/
public static boolean equals(PropertyDescriptor pd, PropertyDescriptor otherPd) {
return (ObjectUtils.nullSafeEquals(pd.getReadMethod(), otherPd.getReadMethod()) &&
ObjectUtils.nullSafeEquals(pd.getWriteMethod(), otherPd.getWriteMethod()) &&
ObjectUtils.nullSafeEquals(pd.getPropertyType(), otherPd.getPropertyType()) &&
ObjectUtils.nullSafeEquals(pd.getPropertyEditorClass(), otherPd.getPropertyEditorClass()) &&
pd.isBound() == otherPd.isBound() && pd.isConstrained() == otherPd.isConstrained());View on GitHub (pinned to e8729d0438)
Solutions
- Make the non-indexed property type an array whose component type equals the indexed element type (e.g. String[] backing String get(int)/set(int,String)).
- If you want collection semantics, drop the indexed accessors and use a single collection-typed property.
- Ensure consistency between simple and indexed accessors when constructing the descriptor.
Example fix
// before: simple type List<String>, indexed returns String
new IndexedPropertyDescriptor("items",
/*read*/ getItemsMethod, /*write*/ setItemsMethod,
/*idxRead*/ getItemIntMethod, /*idxWrite*/ setItemIntMethod);
// getItems() returns List<String> -> mismatch
// after: simple type String[] backing indexed String accessors
private String[] items;
public String[] getItems() { return items; }
public void setItems(String[] items) { this.items = items; }
public String getItems(int i) { return items[i]; }
public void setItems(int i, String v) { items[i] = v; } Defensive patterns
Strategy: type-guard
Validate before calling
static void assertIndexedMatchesNonIndexed(Class<?> propertyType, Method r, Method w) {
Class<?> elem = r != null ? r.getReturnType() : (w != null ? w.getParameterTypes()[1] : null);
if (propertyType != null && elem != null) {
if (!propertyType.isArray() || propertyType.componentType() != elem) {
throw new IllegalStateException(
"Non-indexed type " + propertyType + " must be " + elem + "[]");
}
}
} Type guard
static boolean indexedBackedByArrayOfElement(Class<?> propertyType, Class<?> elementType) {
return propertyType == null || (propertyType.isArray() && propertyType.componentType() == elementType);
} Try / catch
try {
return new IndexedPropertyDescriptor(name, readMethod, writeMethod, idxRead, idxWrite);
} catch (java.beans.IntrospectionException ex) {
if (ex.getMessage().startsWith("Type mismatch between indexed and non-indexed")) {
log.error("Simple accessors must use an array of the indexed element type");
// drop the non-indexed pair and rebuild as indexed-only
return new IndexedPropertyDescriptor(name, null, null, idxRead, idxWrite);
}
throw ex;
} Prevention
- Back indexed properties with an array-typed simple property of matching component type.
- If using collections, drop indexed accessors and use a single collection-typed property.
- Validate the (simpleType, elementType) pair programmatically when building descriptors.
When it happens
Trigger: Calling findIndexedPropertyType with a non-null propertyType that is not an array of the indexed element type - e.g. propertyType=List<String> while indexed accessors return String, or propertyType=String[] while indexed accessors return Integer.
Common situations: An IndexedPropertyDescriptor built where the simple getter/setter pair uses a collection type instead of an array; mixed array/collection accessor pairs on the same property; refactors that changed the backing type from array to List without removing indexed accessors.
Related errors
- Type mismatch between indexed read and write methods: ${inde
- Type mismatch between read and write methods: ${readMethod}
- Bad indexed read method arg count: ${indexedReadMethod}
- Non int index to indexed read method: ${indexedReadMethod}
- Indexed read method returns void: ${indexedReadMethod}
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/6120254280e70c14.json.
Report an issue: GitHub.