{"record":{"id":"42d0c42601503f99","repo":"flowable/flowable-engine","slug":"unexpected-exception-getting-variable-data","errorCode":null,"errorMessage":"Unexpected exception getting variable data","messagePattern":"Unexpected exception getting variable data","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/caze/HistoricCaseInstanceVariableDataResource.java","lineNumber":87,"sourceCode":"                result = (byte[]) variable.getValue();\n                response.setContentType(\"application/octet-stream\");\n\n            } else if (CmmnRestResponseFactory.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 caseInstanceId, String variableName) {\n        HistoricCaseInstance caseObject = getHistoricCaseInstanceFromRequest(caseInstanceId);\n\n        HistoricVariableInstance variable = historyService.createHistoricVariableInstanceQuery()\n                        .caseInstanceId(caseObject.getId())\n                        .variableName(variableName)\n                        .singleResult();\n\n        if (variable == null || variable.getValue() == null) {\n            throw new FlowableObjectNotFoundException(\"Historic case instance '\" + caseInstanceId + \"' variable value for \" + variableName + \" couldn't be found.\", VariableInstanceEntity.class);\n        } else {\n            return restResponseFactory.createRestVariable(variableName, variable.getValue(), null, caseInstanceId, CmmnRestResponseFactory.VARIABLE_HISTORY_CASE, includeBinary);\n        }\n    }\n}","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/caze/HistoricCaseInstanceVariableDataResource.java#L69-L105","documentation":"This FlowableException wraps an IOException that occurred while reading the binary content stream of a historic case instance variable. Flowable stores binary variables as byte arrays on disk or in the database; streaming that content back through the REST API can fail on I/O. It signals a server-side data-read problem, not a client request error.","triggerScenarios":"GET /cmmn-history/historic-case-instances/{caseInstanceId}/variables/{variableName}/data when the variable is a binary/serializable type and reading its content stream throws IOException (corrupt blob, missing file in content store, DB connection dropped mid-stream).","commonSituations":"Binary variable blobs deleted or truncated outside Flowable's transactional control; database unavailable or connection reset; serialized Java objects whose classes are no longer on the server classpath; disk full on content stores backed by the filesystem.","solutions":["Check the server logs for the wrapped IOException cause (getCause()) and fix the underlying storage/DB issue first.","Verify the variable's blob/bytearray row still exists and is not corrupted in the ACT_GE_BYTEARRAY table.","If the variable is a serialized POJO, confirm the class is present on the server classpath and is Serializable.","Restore database or content-store connectivity, then retry the request.","If the blob is unrecoverable, delete and recreate the data or exclude binary variables from the history query."],"exampleFix":"// before\nreturn result; // stream read may throw IOException\n// after\ntry (InputStream content = result) {\n    return IOUtils.toByteArray(content);\n} catch (IOException e) {\n    throw new FlowableException(\"Unexpected exception getting variable data\", e);\n}","handlingStrategy":"try-catch","validationCode":"// Java: list variables first via GET /cmmn-history/historic-case-instances/{id}/variables\n// and check the variable's type is binary/serializable before requesting /data","typeGuard":"boolean isBinaryVariable(RestVariable v) {\n    return v != null && (\"binary\".equals(v.getType()) || \"serializable\".equals(v.getType()));\n}","tryCatchPattern":"try {\n    byte[] data = restClient.getVariableData(caseId, varName);\n} catch (RestClientException e) {\n    log.error(\"Failed to read binary variable data\", e);\n    // surface a generic 'variable data unavailable' to the user\n}","preventionTips":["Always inspect the wrapped cause (FlowableException.getCause()) in server logs.","Monitor DB/content-store health; binary reads fail first when storage degrades.","Keep serialized variable classes stable and on the server classpath.","Avoid storing huge blobs as process variables; use external storage references."],"tags":["io","binary-variable","flowable","rest"],"backgroundTag":"file-read-failed","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"}