flowable/flowable-engine · error · FlowableObjectNotFoundException
The variable does not have a binary data stream.
Error message
The variable does not have a binary data stream.
What it means
Thrown by the Flowable REST history API when a request asks for the binary data of a historic task variable, but the variable's value is not a byte array (or otherwise cannot be streamed as binary content). Only byte[]-valued variables can be returned as a binary data stream; serializable values are Java-serialized and non-binary values have nothing to stream. The error is raised as FlowableObjectNotFoundException because the requested binary content effectively does not exist for this variable.
Source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricTaskInstanceVariableDataResource.java:89
HttpServletResponse response) {
try {
byte[] result = null;
RestVariable variable = getVariableFromRequest(true, taskId, variableName, scope);
if (RestResponseFactory.BYTE_ARRAY_VARIABLE_TYPE.equals(variable.getType())) {
result = (byte[]) variable.getValue();
response.setContentType("application/octet-stream");
} else if (RestResponseFactory.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();View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify the variable is actually a byte[] variable by fetching its metadata via GET /history/historic-task-instances/{taskId}/variables/{variableName} and checking the 'type'/'valueUrl' fields
- Only call the /data sub-resource for binary variables; for simple values read the value directly from the variable JSON response
- If the value should be binary, fix the process that created the variable to store a byte[] (or Serializable) instead of a String
- Catch FlowableObjectNotFoundException on the client and fall back to reading the plain variable value
Example fix
// before
defaultHttpClient.get('/flowable-rest/history/historic-task-instances/' + taskId + '/variables/' + name + '/data')
// after
const meta = await defaultHttpClient.get('/flowable-rest/history/historic-task-instances/' + taskId + '/variables/' + name)
if (meta.data.type === 'binary' || meta.data.valueUrl) {
return defaultHttpClient.get(meta.data.valueUrl, { responseType: 'arraybuffer' })
}
return meta.data.value Defensive patterns
Strategy: validation
Validate before calling
const meta = await api.get(`/history/historic-task-instances/${taskId}/variables/${name}`);
if (!meta.data.valueUrl || meta.data.type !== 'binary') throw new SkipBinaryDownloadError(meta.data.type); Type guard
function isBinaryVariable(meta) { return meta && (meta.type === 'binary' || typeof meta.valueUrl === 'string'); } Try / catch
try { return await api.get(url, {responseType:'arraybuffer'}); } catch (e) { if (e.response && e.response.status === 404) return getPlainVariableValue(taskId, name); throw e; } Prevention
- Fetch variable metadata and check valueUrl before calling the /data endpoint
- Only stream variables you know are stored as byte[]
- Log variable type when a download fails to detect non-binary usage early
When it happens
Trigger: Calling GET /history/historic-task-instances/{taskId}/variables/{variableName}/data when the historic variable's value is not a byte[] (e.g. a plain String, Long, or Date), so the resource's getVariableData falls into the else branch and throws instead of streaming bytes.
Common situations: Front-end code assumes every /data endpoint returns raw bytes and points it at ordinary primitive variables; scripts exporting task attachments call /data on variables that were stored as JSON strings rather than byte arrays; API clients reuse a download URL template for all variable types.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- The variable does not have a binary data stream.
- Historic case instance '${caseInstanceId}' variable value fo
- Could not find a milestone instance with id '${milestoneInst
- Could not find a plan item instance with id '${planItemInsta
- Could not find a task instance with id '${taskId}'.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/24556494cc1baa47.
Report an issue: GitHub.