{"id":"6120254280e70c14","repo":"spring-projects/spring-framework","slug":"type-mismatch-between-indexed-and-non-indexed-meth","errorCode":null,"errorMessage":"Type mismatch between indexed and non-indexed methods: ${indexedReadMethod} - ${indexedWriteMethod}","messagePattern":"Type mismatch between indexed and non-indexed methods: (.+?) - (.+?)","errorType":"exception","errorClass":"IntrospectionException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java","lineNumber":239,"sourceCode":"\t\t\t\t\t// Write method's property type potentially more specific\n\t\t\t\t\tindexedPropertyType = params[1];\n\t\t\t\t}\n\t\t\t\telse if (params[1].isAssignableFrom(indexedPropertyType)) {\n\t\t\t\t\t// Proceed with read method's property type\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthrow new IntrospectionException(\"Type mismatch between indexed read and write methods: \" +\n\t\t\t\t\t\t\tindexedReadMethod + \" - \" + indexedWriteMethod);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tindexedPropertyType = params[1];\n\t\t\t}\n\t\t}\n\n\t\tif (propertyType != null && (!propertyType.isArray() ||\n\t\t\t\tpropertyType.componentType() != indexedPropertyType)) {\n\t\t\tthrow new IntrospectionException(\"Type mismatch between indexed and non-indexed methods: \" +\n\t\t\t\t\tindexedReadMethod + \" - \" + indexedWriteMethod);\n\t\t}\n\n\t\treturn indexedPropertyType;\n\t}\n\n\t/**\n\t * Compare the given {@code PropertyDescriptors} and return {@code true} if\n\t * they are equivalent, i.e. their read method, write method, property type,\n\t * property editor and flags are equivalent.\n\t * @see java.beans.PropertyDescriptor#equals(Object)\n\t */\n\tpublic static boolean equals(PropertyDescriptor pd, PropertyDescriptor otherPd) {\n\t\treturn (ObjectUtils.nullSafeEquals(pd.getReadMethod(), otherPd.getReadMethod()) &&\n\t\t\t\tObjectUtils.nullSafeEquals(pd.getWriteMethod(), otherPd.getWriteMethod()) &&\n\t\t\t\tObjectUtils.nullSafeEquals(pd.getPropertyType(), otherPd.getPropertyType()) &&\n\t\t\t\tObjectUtils.nullSafeEquals(pd.getPropertyEditorClass(), otherPd.getPropertyEditorClass()) &&\n\t\t\t\tpd.isBound() == otherPd.isBound() && pd.isConstrained() == otherPd.isConstrained());","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java#L221-L257","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: simple type List<String>, indexed returns String\nnew IndexedPropertyDescriptor(\"items\",\n    /*read*/ getItemsMethod, /*write*/ setItemsMethod,\n    /*idxRead*/ getItemIntMethod, /*idxWrite*/ setItemIntMethod);\n// getItems() returns List<String> -> mismatch\n\n// after: simple type String[] backing indexed String accessors\nprivate String[] items;\npublic String[] getItems() { return items; }\npublic void setItems(String[] items) { this.items = items; }\npublic String getItems(int i) { return items[i]; }\npublic void setItems(int i, String v) { items[i] = v; }","handlingStrategy":"type-guard","validationCode":"static void assertIndexedMatchesNonIndexed(Class<?> propertyType, Method r, Method w) {\n    Class<?> elem = r != null ? r.getReturnType() : (w != null ? w.getParameterTypes()[1] : null);\n    if (propertyType != null && elem != null) {\n        if (!propertyType.isArray() || propertyType.componentType() != elem) {\n            throw new IllegalStateException(\n                \"Non-indexed type \" + propertyType + \" must be \" + elem + \"[]\");\n        }\n    }\n}","typeGuard":"static boolean indexedBackedByArrayOfElement(Class<?> propertyType, Class<?> elementType) {\n    return propertyType == null || (propertyType.isArray() && propertyType.componentType() == elementType);\n}","tryCatchPattern":"try {\n    return new IndexedPropertyDescriptor(name, readMethod, writeMethod, idxRead, idxWrite);\n} catch (java.beans.IntrospectionException ex) {\n    if (ex.getMessage().startsWith(\"Type mismatch between indexed and non-indexed\")) {\n        log.error(\"Simple accessors must use an array of the indexed element type\");\n        // drop the non-indexed pair and rebuild as indexed-only\n        return new IndexedPropertyDescriptor(name, null, null, idxRead, idxWrite);\n    }\n    throw ex;\n}","preventionTips":["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."],"tags":["property-descriptor","indexed","type-mismatch","introspection","spring-beans"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}