{"record":{"id":"24556494cc1baa47","repo":"flowable/flowable-engine","slug":"the-variable-does-not-have-a-binary-data-stream-245564","errorCode":null,"errorMessage":"The variable does not have a binary data stream.","messagePattern":"The variable does not have a binary data stream\\.","errorType":"http","errorClass":"FlowableObjectNotFoundException","httpStatus":404,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricTaskInstanceVariableDataResource.java","lineNumber":89,"sourceCode":"            HttpServletResponse response) {\n\n        try {\n            byte[] result = null;\n            RestVariable variable = getVariableFromRequest(true, taskId, variableName, scope);\n            if (RestResponseFactory.BYTE_ARRAY_VARIABLE_TYPE.equals(variable.getType())) {\n                result = (byte[]) variable.getValue();\n                response.setContentType(\"application/octet-stream\");\n\n            } else if (RestResponseFactory.SERIALIZABLE_VARIABLE_TYPE.equals(variable.getType())) {\n                ByteArrayOutputStream buffer = new ByteArrayOutputStream();\n                ObjectOutputStream outputStream = new ObjectOutputStream(buffer);\n                outputStream.writeObject(variable.getValue());\n                outputStream.close();\n                result = buffer.toByteArray();\n                response.setContentType(\"application/x-java-serialized-object\");\n\n            } else {\n                throw new FlowableObjectNotFoundException(\"The variable does not have a binary data stream.\", null);\n            }\n            return result;\n\n        } catch (IOException ioe) {\n            // Re-throw IOException\n            throw new FlowableException(\"Unexpected exception getting variable data\", ioe);\n        }\n    }\n\n    public RestVariable getVariableFromRequest(boolean includeBinary, String taskId, String variableName, String scope) {\n        RestVariableScope variableScope = RestVariable.getScopeFromString(scope);\n        HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().taskId(taskId);\n\n        if (variableScope != null) {\n            if (variableScope == RestVariableScope.GLOBAL) {\n                taskQuery.includeProcessVariables();\n            } else {\n                taskQuery.includeTaskLocalVariables();","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricTaskInstanceVariableDataResource.java#L71-L107","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ndefaultHttpClient.get('/flowable-rest/history/historic-task-instances/' + taskId + '/variables/' + name + '/data')\n// after\nconst meta = await defaultHttpClient.get('/flowable-rest/history/historic-task-instances/' + taskId + '/variables/' + name)\nif (meta.data.type === 'binary' || meta.data.valueUrl) {\n  return defaultHttpClient.get(meta.data.valueUrl, { responseType: 'arraybuffer' })\n}\nreturn meta.data.value","handlingStrategy":"validation","validationCode":"const meta = await api.get(`/history/historic-task-instances/${taskId}/variables/${name}`);\nif (!meta.data.valueUrl || meta.data.type !== 'binary') throw new SkipBinaryDownloadError(meta.data.type);","typeGuard":"function isBinaryVariable(meta) { return meta && (meta.type === 'binary' || typeof meta.valueUrl === 'string'); }","tryCatchPattern":"try { return await api.get(url, {responseType:'arraybuffer'}); } catch (e) { if (e.response && e.response.status === 404) return getPlainVariableValue(taskId, name); throw e; }","preventionTips":["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"],"tags":["rest","flowable","binary-data","variable","history"],"backgroundTag":"resource-not-found","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}