{"id":"ffca9f8b1b1af692","repo":"spring-projects/spring-framework","slug":"type-mismatch-between-indexed-read-and-write-metho","errorCode":null,"errorMessage":"Type mismatch between indexed read and write methods: ${indexedReadMethod} - ${indexedWriteMethod}","messagePattern":"Type mismatch between indexed read and write methods: (.+?) - (.+?)","errorType":"exception","errorClass":"IntrospectionException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java","lineNumber":228,"sourceCode":"\n\t\tif (indexedWriteMethod != null) {\n\t\t\tClass<?>[] params = indexedWriteMethod.getParameterTypes();\n\t\t\tif (params.length != 2) {\n\t\t\t\tthrow new IntrospectionException(\"Bad indexed write method arg count: \" + indexedWriteMethod);\n\t\t\t}\n\t\t\tif (params[0] != int.class) {\n\t\t\t\tthrow new IntrospectionException(\"Non int index to indexed write method: \" + indexedWriteMethod);\n\t\t\t}\n\t\t\tif (indexedPropertyType != null) {\n\t\t\t\tif (indexedPropertyType.isAssignableFrom(params[1])) {\n\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/**","sourceCodeStart":210,"sourceCodeEnd":246,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java#L210-L246","documentation":"IntrospectionException from PropertyDescriptorUtils.findIndexedPropertyType when the indexed read method's return type and the indexed write method's second parameter type are mutually non-assignable. Indexed accessors must agree on element type; if neither is assignable to the other the indexed property has an inconsistent type.","triggerScenarios":"getX(int) returns type A, setX(int, B) takes type B with A and B unrelated; refactor changed the element type on one side only.","commonSituations":"Refactor of generic element types; copy-paste accessor pairs with mismatched generics; covariant return on indexed getter not reflected in indexed setter.","solutions":["Align the indexed getter return type and the indexed setter's value parameter to the same element type.","If a more specific setter is intended, ensure the setter value type is assignable from the getter return type.","Regenerate accessors after type changes."],"exampleFix":"// before\npublic Number getItem(int i) { ... }\npublic void setItem(int i, String v) { ... }\n\n// after\npublic Number getItem(int i) { ... }\npublic void setItem(int i, Number v) { ... }","handlingStrategy":"type-guard","validationCode":"static void assertIndexedReadWriteTypesMatch(Method r, Method w) {\n    Class<?> rt = r.getReturnType();\n    Class<?> wt = w.getParameterTypes()[1];\n    if (!rt.isAssignableFrom(wt) && !wt.isAssignableFrom(rt)) {\n        throw new IllegalStateException(\"Indexed getter returns \" + rt + \" setter takes \" + wt);\n    }\n}","typeGuard":"static boolean indexedAccessorsCompatible(Method r, Method w) {\n    Class<?> rt = r.getReturnType();\n    Class<?> wt = w.getParameterTypes()[1];\n    return rt.isAssignableFrom(wt) || wt.isAssignableFrom(rt);\n}","tryCatchPattern":"try {\n    return new IndexedPropertyDescriptor(name, null, null, r, w);\n} catch (java.beans.IntrospectionException ex) {\n    if (ex.getMessage().startsWith(\"Type mismatch between indexed read and write\")) {\n        log.error(\"Fix indexed pair: get returns {} set takes {}\", r.getReturnType(), w.getParameterTypes()[1]);\n    }\n    throw ex;\n}","preventionTips":["Keep indexed getter return type and indexed setter value type identical (or mutually assignable).","Update both indexed accessors when refactoring element type.","Add a test that constructs the IndexedPropertyDescriptor for indexed beans."],"tags":["property-descriptor","indexed","type-mismatch","introspection","spring-beans"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}