flowable/flowable-engine · error · FlowableException
Unexpected exception getting variable data
Error message
Unexpected exception getting variable data
What it means
FlowableException (generic runtime) wrapping an IOException that occurred while serializing a variable's value to the response byte stream. When a historic variable's value is Serializable, the resource writes it with an ObjectOutputStream into a byte buffer; if serialization fails (IO error), this wrapper is thrown. It indicates a server-side serialization failure, not a client mistake.
Source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/task/HistoricTaskInstanceVariableDataResource.java:91
result = (byte[]) variable.getValue();
response.setContentType("application/octet-stream");
} else if (CmmnRestResponseFactory.SERIALIZABLE_VARIABLE_TYPE.equals(variable.getType())) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(buffer);
outputStream.writeObject(variable.getValue());
outputStream.close();
result = buffer.toByteArray();
response.setContentType("application/x-java-serialized-object");
} else {
throw new FlowableObjectNotFoundException("The variable does not have a binary data stream.", null);
}
return result;
} catch (IOException ioe) {
// Re-throw IOException
throw new FlowableException("Unexpected exception getting variable data", ioe);
}
}
public RestVariable getVariableFromRequest(boolean includeBinary, String taskId, String variableName, String scope) {
RestVariableScope variableScope = RestVariable.getScopeFromString(scope);
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().taskId(taskId);
if (variableScope != null) {
if (variableScope == RestVariableScope.GLOBAL) {
taskQuery.includeProcessVariables();
} else {
taskQuery.includeTaskLocalVariables();
}
} else {
taskQuery.includeTaskLocalVariables().includeProcessVariables();
}
HistoricTaskInstance taskObject = taskQuery.singleResult();View on GitHub (pinned to d6d39ce1c6)
Solutions
- Check the cause chain (FlowableException wraps the IOException) for NotSerializableException/InvalidClassException to identify the offending class
- Ensure the custom Serializable class is on the server classpath with a matching serialVersionUID
- Store variables as byte[] or JSON strings instead of raw Serializable custom objects to avoid JDK serialization coupling
- Handle this error client-side as a 500 and fall back to the plain variable endpoint
Example fix
// before
processVariables.put("payload", new LegacyPojo(field)); // serialVersionUID mismatch later
// after
processVariables.put("payload", jsonBytes); // store byte[]/String to avoid JDK serialization Defensive patterns
Strategy: try-catch
Try / catch
try {
return await fetchVariableData(taskId, name);
} catch (e) {
if (String(e.message).includes('Unexpected exception getting variable data')) {
log.error('Serialization failure; cause=' + e.cause); // inspect NotSerializableException / InvalidClassException
return fetchPlainVariable(taskId, name);
}
throw e;
} Prevention
- Avoid storing raw Serializable custom objects in variables; prefer byte[] or JSON strings
- Keep serialVersionUID stable in classes stored as variables and keep them on the server classpath
- Read the wrapped IOException cause to identify the failing class
- Test variable download endpoints after class refactorings and JDK upgrades
When it happens
Trigger: GET .../variables/{variableName}/data on a Serializable variable whose class (or a nested field's class) fails to serialize — typically because the variable's class is not on the server classpath or has an incompatible serialVersionUID at read time.
Common situations: Serializable custom classes stored in variables where the class was later refactored (serialVersionUID changed) and the old engine data can't be deserialized; missing application class on the server for a legacy variable; JDK serialization incompatibility after Java upgrade.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- The variable does not have a binary data stream.
- Historic task instance '' couldn't be found.
- Error getting variable ${variable.getName()}
- The provided body contains a serialized object for which the
- Error getting variable ${variableName}
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/be20c1007aab7b84.
Report an issue: GitHub.