{"record":{"id":"11422caefeb187c6","repo":"spring-projects/spring-framework","slug":"type-mismatch-between-read-and-write-methods-rea","errorCode":null,"errorMessage":"Type mismatch between read and write methods: {readMethod} - {writeMethod}","messagePattern":"Type mismatch between read and write methods: (.+?) - (.+?)","errorType":"exception","errorClass":"IntrospectionException","httpStatus":null,"severity":"error","filePath":"spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java","lineNumber":177,"sourceCode":"\t\t\t\tthrow new IntrospectionException(\"Read method returns void: \" + readMethod);\n\t\t\t}\n\t\t}\n\n\t\tif (writeMethod != null) {\n\t\t\tClass<?>[] params = writeMethod.getParameterTypes();\n\t\t\tif (params.length != 1) {\n\t\t\t\tthrow new IntrospectionException(\"Bad write method arg count: \" + writeMethod);\n\t\t\t}\n\t\t\tif (propertyType != null) {\n\t\t\t\tif (propertyType.isAssignableFrom(params[0])) {\n\t\t\t\t\t// Write method's property type potentially more specific\n\t\t\t\t\tpropertyType = params[0];\n\t\t\t\t}\n\t\t\t\telse if (params[0].isAssignableFrom(propertyType)) {\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(\n\t\t\t\t\t\t\t\"Type mismatch between read and write methods: \" + readMethod + \" - \" + writeMethod);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpropertyType = params[0];\n\t\t\t}\n\t\t}\n\n\t\treturn propertyType;\n\t}\n\n\t/**\n\t * See {@link java.beans.IndexedPropertyDescriptor#findIndexedPropertyType}.\n\t */\n\tpublic static @Nullable Class<?> findIndexedPropertyType(String name, @Nullable Class<?> propertyType,\n\t\t\t@Nullable Method indexedReadMethod, @Nullable Method indexedWriteMethod) throws IntrospectionException {\n\n\t\tClass<?> indexedPropertyType = null;","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-beans/src/main/java/org/springframework/beans/PropertyDescriptorUtils.java#L159-L195","documentation":"Thrown as java.beans.IntrospectionException by PropertyDescriptorUtils.findPropertyType when both a read method and a write method are supplied and their property types are mutually non-assignable. The getter return type and setter parameter type must be in an assignable relationship for the property to have a single coherent type.","triggerScenarios":"findPropertyType(readMethod, writeMethod) computes propertyType from the getter, then checks writeMethod.getParameterTypes()[0]; if neither propertyType.isAssignableFrom(param[0]) nor param[0].isAssignableFrom(propertyType), it throws.","commonSituations":"A getter returns Number but the setter takes String (or vice versa), overloading that creates an inconsistent read/write pair, refactoring a field's type without updating both accessors, or Lombok @Delegate / generated code producing mismatched pairs.","solutions":["Align the getter return type and setter parameter type (make one assignable to the other, ideally identical).","Remove the conflicting overload or rename one of the accessors.","Regenerate the class with consistent accessor types."],"exampleFix":"// before\npublic Number getValue() { ... }\npublic void setValue(String v) { ... }\n\n// after\npublic String getValue() { ... }\npublic void setValue(String v) { ... }","handlingStrategy":"validation","validationCode":"// before declaring the property consistent\nClass<?> readType = readMethod.getReturnType();\nClass<?> writeType = writeMethod.getParameterTypes()[0];\nif (!readType.isAssignableFrom(writeType) && !writeType.isAssignableFrom(readType)) {\n    throw new IllegalStateException(\"read/write type clash: \" + readType + \" vs \" + writeType);\n}","typeGuard":"static boolean accessorTypesConsistent(Method read, Method write) {\n    Class<?> r = read.getReturnType();\n    Class<?> w = write.getParameterTypes()[0];\n    return r.isAssignableFrom(w) || w.isAssignableFrom(r);\n}","tryCatchPattern":null,"preventionTips":["Keep getter return type and setter parameter type identical, or at least one assignable to the other.","When refactoring a field type, update BOTH accessors in the same commit.","Avoid overloaded accessors that change the property's apparent type."],"tags":["property-descriptor","introspection","javabeans","type-mismatch","spring-beans"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}