{"record":{"id":"72d61119d7f2d7f8","repo":"flowable/flowable-engine","slug":"unexpected-exception-getting-variable-data-72d611","errorCode":null,"errorMessage":"Unexpected exception getting variable data","messagePattern":"Unexpected exception getting variable data","errorType":"exception","errorClass":"FlowableException","httpStatus":500,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricProcessInstanceVariableDataResource.java","lineNumber":87,"sourceCode":"                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 processInstanceId, String variableName) {\n\n        HistoricProcessInstance processObject = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).includeProcessVariables().singleResult();\n\n        if (processObject == null) {\n            throw new FlowableObjectNotFoundException(\"Historic process instance '\" + processInstanceId + \"' could not be found.\", HistoricProcessInstanceEntity.class);\n        }\n        \n        if (restApiInterceptor != null) {\n            restApiInterceptor.accessHistoryProcessInfoById(processObject);\n        }\n\n        Object value = processObject.getProcessVariables().get(variableName);\n\n        if (value == null) {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricProcessInstanceVariableDataResource.java#L69-L105","documentation":"While serializing a historic variable's value to bytes for the /data endpoint, an IOException can occur (e.g. the value is not java.io.Serializable or serialization fails). The resource wraps it in a FlowableException with the generic message \"Unexpected exception getting variable data\" and the IOException as cause.","triggerScenarios":"GET /history/process-instances/{id}/variables/{name}/data where the serializable variable's stored object cannot be serialized back to bytes (non-serializable class, classpath/serialization-version mismatch, corrupted stored value).","commonSituations":"Variable payload classes changed between deployments so serialVersionUID no longer matches; storing objects of classes missing implements Serializable; engine/database upgrades leaving incompatible serialized blobs.","solutions":["Inspect the wrapped IOException cause in server logs for the real serialization error","Ensure values stored as serializable variables implement java.io.Serializable with a stable serialVersionUID","Store simple JSON strings or byte arrays instead of raw Java objects to avoid deserialization coupling","Check that the REST server's classpath contains the variable payload classes at the same version used when the variable was written"],"exampleFix":"// before\nclass ReportData { String title; }                       // not Serializable\n// after\nclass ReportData implements java.io.Serializable {\n    private static final long serialVersionUID = 1L;\n    String title;\n}","handlingStrategy":"try-catch","validationCode":"const v = await get(`/history/process-instances/${pid}/variables/${name}`); if (v.type === 'serializable' && !v.valueUrl) throw new Error('serializable payload may be unreadable');","typeGuard":"const isSerializableType = (v) => v?.type === 'serializable';","tryCatchPattern":"catch (e) { if (e.response && e.response.status >= 500 && /Unexpected exception getting variable data/.test(e.response.data.message || '')) { /* inspect server logs for the IOException cause */ } throw e; }","preventionTips":["Make all variable payload classes Serializable with fixed serialVersionUID","Avoid storing raw Java objects; prefer JSON strings or byte arrays","Keep payload class versions in sync across services and deployments"],"tags":["rest-api","variables","serialization","io"],"backgroundTag":"internal-invariant-violation","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"}