quarkusio/quarkus · error · RuntimeException

Cannot serialise field '${i.getName()}' on object '${param}'

Error message

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()}'.

What it means

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.

Source

Thrown at core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java:1431

                            if (relaxedValidation) {
                                //this is a weird situation where the reader and writer are different types
                                //we iterate and try and find a valid setter method for the type we have
                                //OpenAPI does some weird stuff like this

                                for (Method m : param.getClass().getMethods()) {
                                    if (m.getName().equals(i.getWriteMethod().getName())) {
                                        if (m.getParameterCount() > 0) {
                                            Class<?>[] parameterTypes = m.getParameterTypes();
                                            if (parameterTypes[0].isAssignableFrom(param.getClass())) {
                                                propertyType = parameterTypes[0];
                                                break;
                                            }
                                        }
                                    }

                                }
                            } else {
                                throw new RuntimeException("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()
                                        + "'.");
                            }
                        }
                    }
                    DeferredParameter val;
                    try {
                        val = loadObjectInstance(propertyValue, existing,
                                i.getPropertyType(), relaxedValidation);
                    } catch (Exception e) {
                        throw new RuntimeException(
                                "Couldn't load object of type " + i.propertyType.getName() + " for property '" + i.getName()
                                        + "' on object '" + param
                                        + "'. Please, check the Bytecode Recording documentation " +
                                        "https://quarkus.io/guides/writing-extensions#bytecode-recording to be sure this type "

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make the setter's parameter type exactly match the getter's return type
  2. Rename the offending setter if it is genuinely a different property
  3. Exclude the property from recording (register a custom constructor handler or restructure the class)

Example fix

// before
public String getMode() {...}
public void setMode(Object mode) {...}
// after
public String getMode() {...}
public void setMode(String mode) {...}
Defensive patterns

Strategy: type-guard

Validate before calling

Method getter = ...; Method setter = ...;
if (!getter.getReturnType().equals(setter.getParameterTypes()[0])) {
    throw new IllegalStateException("Getter/setter type mismatch for " + getter.getName());
}

Type guard

boolean propTypesMatch(Method getter, Method setter) {
    return setter.getParameterCount() == 1
        && setter.getParameterTypes()[0].equals(getter.getReturnType());
}

Try / catch

try {
    recorder.record(value);
} catch (RuntimeException e) {
    if (String.valueOf(e.getMessage()).contains("getter and setter are of different types")) {
        throw new IllegalStateException("Align getter/setter types on " + value.getClass(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/1b65ce8a4e4b2064. Report an issue: GitHub.