mybatis/mybatis-3 · error · ExecutorException
Property [" + this.property + "] cannot be loaded because re
Error message
Property [" + this.property + "] cannot be loaded because required parameter of mapped statement [" + this.mappedStatement + "] is not serializable."
What it means
A LoadPair can be serialized along with a lazy-loading proxy so the property can be fetched after deserialization, but that only works if the query parameter object is itself serializable. If it was not, mappedParameter is lost (null) on the deserialized side; when load() later runs with metaResultObject/resultLoader also null, it cannot reconstruct the query and throws this ExecutorException.
Source
Thrown at src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java:195
public void load() throws SQLException {
/*
* These field should not be null unless the loadpair was serialized. Yet in that case this method should not be
* called.
*/
if (this.metaResultObject == null) {
throw new IllegalArgumentException("metaResultObject is null");
}
if (this.resultLoader == null) {
throw new IllegalArgumentException("resultLoader is null");
}
this.load(null);
}
public void load(final Object userObject) throws SQLException {
if (this.metaResultObject == null || this.resultLoader == null) {
if (this.mappedParameter == null) {
throw new ExecutorException("Property [" + this.property + "] cannot be loaded because "
+ "required parameter of mapped statement [" + this.mappedStatement + "] is not serializable.");
}
final Configuration config = this.getConfiguration();
final MappedStatement ms = config.getMappedStatement(this.mappedStatement);
if (ms == null) {
throw new ExecutorException(
"Cannot lazy load property [" + this.property + "] of deserialized object [" + userObject.getClass()
+ "] because configuration does not contain statement [" + this.mappedStatement + "]");
}
this.metaResultObject = config.newMetaObject(userObject);
this.resultLoader = new ResultLoader(config, new ClosedExecutor(), ms, this.mappedParameter,
metaResultObject.getSetterType(this.property), null, null);
}
/*
* We are using a new executor because we may be (and likely are) on a new thread and executors aren't threadView on GitHub (pinned to 008069adb1)
Solutions
- Implement java.io.Serializable on the parameter class(es) used by the nested select
- Disable lazy loading / use fetchType="eager" for objects that will be serialized
- Load the lazy property before serializing the object
Example fix
// before
class OrderQuery { Long customerId; } // not serializable
// after
class OrderQuery implements java.io.Serializable { private static final long serialVersionUID = 1L; Long customerId; } Defensive patterns
Strategy: validation
Validate before calling
// Ensure nested-select parameter types are serializable before enabling lazy proxies in caches
Object probe = nestedSelectParameterFactory.create();
if (!(probe instanceof java.io.Serializable)) {
throw new IllegalStateException("parameter for nested select must be Serializable to support deserialized lazy loading");
} Try / catch
try { user.getOrders(); } catch (PersistenceException e) { if (String.valueOf(e.getMessage()).contains("not serializable")) { /* refetch entity from DB */ } else throw e; } Prevention
- Mark all parameter classes of nested selects as java.io.Serializable
- Eagerly load associations on entities stored in distributed caches
When it happens
Trigger: A nested select whose parameter object (or one of its nested values) does not implement java.io.Serializable, followed by serialize -> deserialize -> read of the lazy property in the new JVM.
Common situations: Distributed caches (Redis, Hazelcast) or HTTP sessions holding MyBatis lazy proxies; domain classes never marked Serializable because the app previously did not serialize them.
Related errors
- Cannot lazy load property [" + this.property + "] of deseria
- An attempt has been made to read a not loaded lazy property
- Cannot get Configuration as configuration factory was not se
- SharedCache failed to make a copy of a non-serializable obje
- Error serializing object. Cause: ${cause}
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/947c7f75573ccb11.
Report an issue: GitHub.