{"record":{"id":"947c7f75573ccb11","repo":"mybatis/mybatis-3","slug":"property-this-property-cannot-be-loaded","errorCode":null,"errorMessage":"Property [\" + this.property + \"] cannot be loaded because required parameter of mapped statement [\" + this.mappedStatement + \"] is not serializable.\"","messagePattern":"Property \\[\" \\+ this\\.property \\+ \"\\] cannot be loaded because required parameter of mapped statement \\[\" \\+ this\\.mappedStatement \\+ \"\\] is not serializable\\.\"","errorType":"exception","errorClass":"ExecutorException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java","lineNumber":195,"sourceCode":"    public void load() throws SQLException {\n      /*\n       * These field should not be null unless the loadpair was serialized. Yet in that case this method should not be\n       * called.\n       */\n      if (this.metaResultObject == null) {\n        throw new IllegalArgumentException(\"metaResultObject is null\");\n      }\n      if (this.resultLoader == null) {\n        throw new IllegalArgumentException(\"resultLoader is null\");\n      }\n\n      this.load(null);\n    }\n\n    public void load(final Object userObject) throws SQLException {\n      if (this.metaResultObject == null || this.resultLoader == null) {\n        if (this.mappedParameter == null) {\n          throw new ExecutorException(\"Property [\" + this.property + \"] cannot be loaded because \"\n              + \"required parameter of mapped statement [\" + this.mappedStatement + \"] is not serializable.\");\n        }\n\n        final Configuration config = this.getConfiguration();\n        final MappedStatement ms = config.getMappedStatement(this.mappedStatement);\n        if (ms == null) {\n          throw new ExecutorException(\n              \"Cannot lazy load property [\" + this.property + \"] of deserialized object [\" + userObject.getClass()\n                  + \"] because configuration does not contain statement [\" + this.mappedStatement + \"]\");\n        }\n\n        this.metaResultObject = config.newMetaObject(userObject);\n        this.resultLoader = new ResultLoader(config, new ClosedExecutor(), ms, this.mappedParameter,\n            metaResultObject.getSetterType(this.property), null, null);\n      }\n\n      /*\n       * We are using a new executor because we may be (and likely are) on a new thread and executors aren't thread","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java#L177-L213","documentation":"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.","triggerScenarios":"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.","commonSituations":"Distributed caches (Redis, Hazelcast) or HTTP sessions holding MyBatis lazy proxies; domain classes never marked Serializable because the app previously did not serialize them.","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"],"exampleFix":"// before\nclass OrderQuery { Long customerId; } // not serializable\n\n// after\nclass OrderQuery implements java.io.Serializable { private static final long serialVersionUID = 1L; Long customerId; }","handlingStrategy":"validation","validationCode":"// Ensure nested-select parameter types are serializable before enabling lazy proxies in caches\nObject probe = nestedSelectParameterFactory.create();\nif (!(probe instanceof java.io.Serializable)) {\n  throw new IllegalStateException(\"parameter for nested select must be Serializable to support deserialized lazy loading\");\n}","typeGuard":null,"tryCatchPattern":"try { user.getOrders(); } catch (PersistenceException e) { if (String.valueOf(e.getMessage()).contains(\"not serializable\")) { /* refetch entity from DB */ } else throw e; }","preventionTips":["Mark all parameter classes of nested selects as java.io.Serializable","Eagerly load associations on entities stored in distributed caches"],"tags":["lazy-loading","serialization","deserialization"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}