{"record":{"id":"99e06cb00072806e","repo":"flowable/flowable-engine","slug":"couldn-t-deserialize-object-in-variable","errorCode":null,"errorMessage":"Couldn't deserialize object in variable ''","messagePattern":"Couldn't deserialize object in variable ''","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/SerializableType.java","lineNumber":120,"sourceCode":"            oos = createObjectOutputStream(baos);\n            oos.writeObject(value);\n        } catch (Exception e) {\n            throw new ActivitiException(\"Couldn't serialize value '\" + value + \"' in variable '\" + valueFields.getName() + \"'\", e);\n        } finally {\n            IoUtil.closeSilently(oos);\n        }\n        return baos.toByteArray();\n    }\n\n    public Object deserialize(byte[] bytes, ValueFields valueFields) {\n        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);\n        try {\n            ObjectInputStream ois = createObjectInputStream(bais);\n            Object deserializedObject = ois.readObject();\n\n            return deserializedObject;\n        } catch (Exception e) {\n            throw new ActivitiException(\"Couldn't deserialize object in variable '\" + valueFields.getName() + \"'\", e);\n        } finally {\n            IoUtil.closeSilently(bais);\n        }\n    }\n\n    @Override\n    public boolean isAbleToStore(Object value) {\n        // TODO don't we need null support here?\n        return value instanceof Serializable;\n    }\n\n    protected ObjectInputStream createObjectInputStream(InputStream is) throws IOException {\n        return new ObjectInputStream(is) {\n            @Override\n            protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {\n                return ReflectUtil.loadClass(desc.getName());\n            }\n        };","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/SerializableType.java#L102-L138","documentation":"Thrown by SerializableType.deserialize when reading a stored, Java-serialized variable back with ObjectInputStream fails. The variable name is included in the message and the underlying exception (ClassNotFoundException, InvalidClassException, IOException, StreamCorruptedException) is the cause.","triggerScenarios":"Reading a serializable variable whose class is not on the classpath (ClassNotFoundException), whose serialVersionUID changed (InvalidClassException), or whose stored bytes are corrupt/migrated between formats.","commonSituations":"Upgrading the application and changing variable class definitions without serialVersionUID; moving variables between databases/environments; removing old DTO classes from the classpath; switching JVMs with incompatible serialization.","solutions":["Restore the class (or a compatible version with matching serialVersionUID) to the classpath.","Add a fixed serialVersionUID to variable classes and keep it stable across releases.","Inspect the cause: ClassNotFoundException -> deployment/classpath issue; InvalidClassException -> schema change; StreamCorruptedException -> data corruption.","Migrate legacy variables to a stable format (e.g. JSON) or re-create them.","Catch ActivitiException around variable reads and fall back to re-initializing the variable."],"exampleFix":"// before\npublic class OrderData { /* no serialVersionUID, fields changed */ }\n// after\npublic class OrderData implements Serializable {\n    private static final long serialVersionUID = 1L;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { Object v = taskService.getVariable(taskId, \"order\"); } catch (ActivitiException e) {\n  log.error(\"Deserializing variable 'order' failed: {}\", e.getCause(), e);\n  // fallback: re-initialize or migrate the variable\n}","preventionTips":["Declare explicit serialVersionUID on variable classes","Never remove or rename historically persisted variable classes without a migration","Keep variable DTOs on the classpath of every service that reads them","Avoid Java serialization for cross-version persistence; prefer stable formats"],"tags":["serialization","classpath","deserialization"],"backgroundTag":"class-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}