{"record":{"id":"69ea83b2784cd015","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: {} - {}","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/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java#L210-L246","documentation":"Thrown when an indexed property has both an indexed read method (getX(int)) and an indexed write method (setX(int, T)) whose element types are mutually incompatible — neither is assignable to the other. This is the IntrospectionException raised at line 228, mirroring java.beans.IndexedPropertyDescriptor.findIndexedPropertyType. It prevents Spring from determining a single coherent property type.","triggerScenarios":"A class declares e.g. String getItem(int i) and void setItem(int i, Integer value). In findIndexedPropertyType(), neither String.isAssignableFrom(Integer) nor Integer.isAssignableFrom(String) holds, so the mismatch branch throws.","commonSituations":"Copy-paste errors when generating getters/setters; mixing a read method that returns a String with a setter taking a numeric wrapper; legacy beans where the indexed getter/setter were written at different times with drifted types.","solutions":["Make the indexed getter's return type and the indexed setter's second-parameter type identical (or at least one assignable to the other).","If the types genuinely differ, drop the conflicting method so only one indexed accessor remains.","Regenerate accessors with the IDE so both use the same field type."],"exampleFix":"// before\npublic String getItem(int i) { return items[i]; }\npublic void setItem(int i, Integer v) { items[i] = v; }\n\n// after\npublic String getItem(int i) { return items[i]; }\npublic void setItem(int i, String v) { items[i] = v; }","handlingStrategy":"validation","validationCode":"// Assert indexed read/write element types agree before binding\nClass<?> readE = readMethod.getReturnType();\nClass<?> writeE = writeMethod.getParameterTypes()[1];\nif (!readE.isAssignableFrom(writeE) && !writeE.isAssignableFrom(readE)) {\n    throw new IllegalStateException(\"indexed element types incompatible: \" + readE + \" vs \" + writeE);\n}","typeGuard":"static boolean indexedTypesAgree(Method read, Method write) {\n    Class<?> r = read.getReturnType();\n    Class<?> w = write.getParameterTypes()[1];\n    return r.isAssignableFrom(w) || w.isAssignableFrom(r);\n}","tryCatchPattern":null,"preventionTips":["Derive both indexed accessors from a single typed field.","Add a unit test that introspects the bean via PropertyDescriptorUtils.findIndexedPropertyType to fail fast.","Regenerate accessors together after a field type change."],"tags":["java-beans","introspection","indexed-property","type-mismatch"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}