flowable/flowable-engine · error · ActivitiException
Couldn't deserialize object in variable ''
Error message
Couldn't deserialize object in variable ''
What it means
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.
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.
Example fix
// before
public class OrderData { /* no serialVersionUID, fields changed */ }
// after
public class OrderData implements Serializable {
private static final long serialVersionUID = 1L;
} Defensive patterns
Strategy: try-catch
Try / catch
try { Object v = taskService.getVariable(taskId, "order"); } catch (ActivitiException e) {
log.error("Deserializing variable 'order' failed: {}", e.getCause(), e);
// fallback: re-initialize or migrate the variable
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- The provided body contains a serialized object for which…
- The provided body contains a serialized object for which…
- The provided body contains a serialized object for which…
- The provided body contains a serialized object for which…
- Unexpected exception when deserializing JPA id's
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/99e06cb00072806e.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/SerializableType.java:120
oos = createObjectOutputStream(baos);
oos.writeObject(value);
} catch (Exception e) {
throw new ActivitiException("Couldn't serialize value '" + value + "' in variable '" + valueFields.getName() + "'", e);
} finally {
IoUtil.closeSilently(oos);
}
return baos.toByteArray();
}
public Object deserialize(byte[] bytes, ValueFields valueFields) {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
try {
ObjectInputStream ois = createObjectInputStream(bais);
Object deserializedObject = ois.readObject();
return deserializedObject;
} catch (Exception e) {
throw new ActivitiException("Couldn't deserialize object in variable '" + valueFields.getName() + "'", e);
} finally {
IoUtil.closeSilently(bais);
}
}
@Override
public boolean isAbleToStore(Object value) {
// TODO don't we need null support here?
return value instanceof Serializable;
}
protected ObjectInputStream createObjectInputStream(InputStream is) throws IOException {
return new ObjectInputStream(is) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
return ReflectUtil.loadClass(desc.getName());
}
};View on GitHub (pinned to d6d39ce1c6)