{"record":{"id":"879640aa30ebf2fc","repo":"mybatis/mybatis-3","slug":"error-serializing-object-cause-cause","errorCode":null,"errorMessage":"Error serializing object.  Cause: ${cause}","messagePattern":"Error serializing object\\.  Cause: (.+?)","errorType":"exception","errorClass":"CacheException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java","lineNumber":94,"sourceCode":"\n  @Override\n  public int hashCode() {\n    return delegate.hashCode();\n  }\n\n  @Override\n  public boolean equals(Object obj) {\n    return delegate.equals(obj);\n  }\n\n  private byte[] serialize(Serializable value) {\n    try (ByteArrayOutputStream bos = new ByteArrayOutputStream();\n        ObjectOutputStream oos = new ObjectOutputStream(bos)) {\n      oos.writeObject(value);\n      oos.flush();\n      return bos.toByteArray();\n    } catch (Exception e) {\n      throw new CacheException(\"Error serializing object.  Cause: \" + e, e);\n    }\n  }\n\n  private Serializable deserialize(byte[] value) {\n    SerialFilterChecker.check();\n    Serializable result;\n    try (ByteArrayInputStream bis = new ByteArrayInputStream(value);\n        ObjectInputStream ois = new CustomObjectInputStream(bis)) {\n      result = (Serializable) ois.readObject();\n    } catch (Exception e) {\n      throw new CacheException(\"Error deserializing object.  Cause: \" + e, e);\n    }\n    return result;\n  }\n\n  public static class CustomObjectInputStream extends ObjectInputStream {\n\n    public CustomObjectInputStream(InputStream in) throws IOException {","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/cache/decorators/SerializedCache.java#L76-L112","documentation":"Thrown by SerializedCache.serialize() when Java ObjectOutputStream fails while converting a cached value to bytes: the object passed the instanceof Serializable check but serialization itself errored (a nested non-serializable field, a Serializable class whose writeObject throws, or an I/O failure inside the stream). The original exception is chained as the cause and mirrored in the message.","triggerScenarios":"Caching an object whose top-level class implements Serializable but a field's type does not (NotSerializableException deep in the graph); a custom writeObject/readObject throwing; graph cycles or StackOverflowError during serialization of deeply nested lazy-loaded proxies.","commonSituations":"Entities with lazy-loading proxies (mybatis lazy loading wrapped objects) whose enhancer state is not serializable; adding a new field of a library type (e.g. java.lang.Thread, an InputStream wrapper) to a cached entity; serialization filters (JEP 290) rejecting a class in newer JDKs.","solutions":["Inspect the cause: NotSerializableException names the exact offending class — make that class Serializable or mark the field transient","Remove non-data fields from cached result types, or map them with a typeHandler that stores a serializable representation","Check JEP 290 serialization filters / SerialFilterChecker constraints if classes are being rejected by policy"],"exampleFix":"// before\npublic class Order implements Serializable {\n  private transient OrderStateListener listener; // was NOT transient -> NotSerializableException\n}\n\n// after\npublic class Order implements Serializable {\n  private transient OrderStateListener listener;\n}","handlingStrategy":"try-catch","validationCode":"// pre-flight in tests: round-trip the entity\nnew ObjectOutputStream(new ByteArrayOutputStream()).writeObject(sampleEntity); // throws NotSerializableException naming the field type","typeGuard":"static boolean safelySerializable(Object o) { try { serialize(o); return true; } catch (Exception e) { return false; } }","tryCatchPattern":"catch (CacheException e) { if (e.getCause() instanceof NotSerializableException) { mark type non-cacheable / disable cache for that mapper and log; } else throw e; }","preventionTips":["Round-trip test every cached entity type in CI","Mark infrastructure fields transient","Watch JEP 290 filters on newer JDKs"],"tags":["mybatis","second-level-cache","serialization"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}