{"record":{"id":"1b65ce8a4e4b2064","repo":"quarkusio/quarkus","slug":"cannot-serialise-field-i-getname-on-object-1b65ce","errorCode":null,"errorMessage":"Cannot serialise field '${i.getName()}' on object '${param}' of type '${param.getClass().getName()}' as getter and setter are of different types. Getter type is '${getterReturnType.getName()}' while setter type is '${setterParameterType.getName()}'.","messagePattern":"Cannot serialise field '(.+?)' on object '(.+?)' of type '(.+?)' as getter and setter are of different types\\. Getter type is '(.+?)' while setter type is '(.+?)'\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java","lineNumber":1431,"sourceCode":"                            if (relaxedValidation) {\n                                //this is a weird situation where the reader and writer are different types\n                                //we iterate and try and find a valid setter method for the type we have\n                                //OpenAPI does some weird stuff like this\n\n                                for (Method m : param.getClass().getMethods()) {\n                                    if (m.getName().equals(i.getWriteMethod().getName())) {\n                                        if (m.getParameterCount() > 0) {\n                                            Class<?>[] parameterTypes = m.getParameterTypes();\n                                            if (parameterTypes[0].isAssignableFrom(param.getClass())) {\n                                                propertyType = parameterTypes[0];\n                                                break;\n                                            }\n                                        }\n                                    }\n\n                                }\n                            } else {\n                                throw new RuntimeException(\"Cannot serialise field '\" + i.getName() + \"' on object '\" + param\n                                        + \"' of type '\" + param.getClass().getName()\n                                        + \"' as getter and setter are of different types. Getter type is '\"\n                                        + getterReturnType.getName() + \"' while setter type is '\"\n                                        + setterParameterType.getName()\n                                        + \"'.\");\n                            }\n                        }\n                    }\n                    DeferredParameter val;\n                    try {\n                        val = loadObjectInstance(propertyValue, existing,\n                                i.getPropertyType(), relaxedValidation);\n                    } catch (Exception e) {\n                        throw new RuntimeException(\n                                \"Couldn't load object of type \" + i.propertyType.getName() + \" for property '\" + i.getName()\n                                        + \"' on object '\" + param\n                                        + \"'. Please, check the Bytecode Recording documentation \" +\n                                        \"https://quarkus.io/guides/writing-extensions#bytecode-recording to be sure this type \"","sourceCodeStart":1413,"sourceCodeEnd":1449,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java#L1413-L1449","documentation":"The recorder pairs getters and setters by property name and requires their types to match, since the recorded value read by the getter is replayed through the setter. If getter return type and setter parameter type differ (including generics/boxing mismatches), the generated bytecode would be invalid, so Quarkus rejects the object.","triggerScenarios":"A class where getX() returns String but setX(Object) or setX(CharSequence) exists; covariant override of a getter with a mismatched setter; generic property where erasure changes the setter's parameter type.","commonSituations":"Refactorings that widened or narrowed a property type on only one side; interfaces with generified getters implemented with raw setters; fluent setters that return the object but take a different type.","solutions":["Make the setter's parameter type exactly match the getter's return type","Rename the offending setter if it is genuinely a different property","Exclude the property from recording (register a custom constructor handler or restructure the class)"],"exampleFix":"// before\npublic String getMode() {...}\npublic void setMode(Object mode) {...}\n// after\npublic String getMode() {...}\npublic void setMode(String mode) {...}","handlingStrategy":"type-guard","validationCode":"Method getter = ...; Method setter = ...;\nif (!getter.getReturnType().equals(setter.getParameterTypes()[0])) {\n    throw new IllegalStateException(\"Getter/setter type mismatch for \" + getter.getName());\n}","typeGuard":"boolean propTypesMatch(Method getter, Method setter) {\n    return setter.getParameterCount() == 1\n        && setter.getParameterTypes()[0].equals(getter.getReturnType());\n}","tryCatchPattern":"try {\n    recorder.record(value);\n} catch (RuntimeException e) {\n    if (String.valueOf(e.getMessage()).contains(\"getter and setter are of different types\")) {\n        throw new IllegalStateException(\"Align getter/setter types on \" + value.getClass(), e);\n    }\n    throw e;\n}","preventionTips":["Never widen/narrow only one side of a property pair","Avoid raw generics on setters whose getters are generified","Check covariant overrides keep setter signatures in sync"],"tags":["quarkus","bytecode-recording","type-mismatch"],"backgroundTag":"getter-setter-type-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}