{"record":{"id":"0f3876c831793795","repo":"flowable/flowable-engine","slug":"error-reading-json-info-node-for-process-definitio","errorCode":null,"errorMessage":"Error reading json info node for process definition \" + processDefinitionId","messagePattern":"Error reading json info node for process definition \" \\+ processDefinitionId","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/deploy/ProcessDefinitionInfoCache.java","lineNumber":148,"sourceCode":"        ProcessDefinitionInfoCacheObject cacheObject = null;\n        if (cache.containsKey(processDefinitionId)) {\n            cacheObject = cache.get(processDefinitionId);\n        } else {\n            cacheObject = new ProcessDefinitionInfoCacheObject();\n            cacheObject.setRevision(0);\n            cacheObject.setInfoNode(objectMapper.createObjectNode());\n        }\n\n        ProcessDefinitionInfoEntity infoEntity = infoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId);\n        if (infoEntity != null && infoEntity.getRevision() != cacheObject.getRevision()) {\n            cacheObject.setRevision(infoEntity.getRevision());\n            if (infoEntity.getInfoJsonId() != null) {\n                byte[] infoBytes = infoEntityManager.findInfoJsonById(infoEntity.getInfoJsonId());\n                try {\n                    ObjectNode infoNode = (ObjectNode) objectMapper.readTree(infoBytes);\n                    cacheObject.setInfoNode(infoNode);\n                } catch (Exception e) {\n                    throw new FlowableException(\"Error reading json info node for process definition \" + processDefinitionId, e);\n                }\n            }\n        } else if (infoEntity == null) {\n            cacheObject.setRevision(0);\n            cacheObject.setInfoNode(objectMapper.createObjectNode());\n        }\n\n        return cacheObject;\n    }\n\n}\n","sourceCodeStart":130,"sourceCodeEnd":160,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/deploy/ProcessDefinitionInfoCache.java#L130-L160","documentation":"Flowable caches process-definition info (JSON metadata stored via ProcessDefinitionInfoEntity). When the stored info JSON bytes cannot be parsed into an ObjectNode by Jackson, retrieveProcessDefinitionInfoCacheObject wraps the parse failure in a FlowableException naming the process definition. The root cause is corrupt, truncated, or non-JSON bytes behind infoJsonId in the database.","triggerScenarios":"Calling RuntimeService/RepositoryService APIs that resolve process definition info (e.g. getProcessDefinitionInfo) when the ACT_GE_BYTEARRAY row referenced by infoEntity.getInfoJsonId() contains bytes that objectMapper.readTree() cannot parse (corrupt row, manual DB edit, wrong encoding, or a non-JSON blob written by another tool).","commonSituations":"Manual database manipulation or partial restores of Flowable schema tables (ACT_GE_BYTEARRAY), DB character-set/encoding migrations that mangle BLOB contents, upgrades where info JSON was written by an incompatible serializer, disk/storage corruption behind the blob column.","solutions":["Inspect the ACT_GE_BYTEARRAY row for infoEntity.getInfoJsonId() and verify its bytes are valid JSON (e.g. SELECT and validate with a JSON parser).","Redeploy the process definition (or re-save the process definition info) so a fresh, valid JSON info node is written and the stale/corrupt blob is replaced.","Check database charset/encoding settings for the blob column; fix mismatched encoding and re-write the bytes.","Clear any externally persisted cache and retry after the underlying data is fixed; if parsing was failing due to transient I/O, re-fetching the bytes may succeed."],"exampleFix":"// before (corrupt blob parsed blindly)\nbyte[] infoBytes = infoEntityManager.findInfoJsonById(infoEntity.getInfoJsonId());\nObjectNode infoNode = (ObjectNode) objectMapper.readTree(infoBytes);\n// after (caller-side guard + repair path)\nbyte[] infoBytes = infoEntityManager.findInfoJsonById(infoEntity.getInfoJsonId());\nJsonNode raw = objectMapper.readTree(infoBytes);\nif (raw == null || !raw.isObject()) {\n    // fall back to empty info node and re-publish definition info\n    cacheObject.setInfoNode(objectMapper.createObjectNode());\n} else {\n    cacheObject.setInfoNode((ObjectNode) raw);\n}","handlingStrategy":"try-catch","validationCode":"// Java: validate blob before use\nJsonNode check(byte[] bytes, ObjectMapper om) {\n    try { return om.readTree(bytes); } catch (Exception e) { return null; }\n}","typeGuard":"boolean isValidInfoJson(JsonNode n) { return n != null && n.isObject(); }","tryCatchPattern":"try {\n    ObjectNode node = (ObjectNode) objectMapper.readTree(infoBytes);\n    cacheObject.setInfoNode(node);\n} catch (FlowableException e) {\n    // inspect/repair ACT_GE_BYTEARRAY row or fall back to empty node\n    cacheObject.setInfoNode(objectMapper.createObjectNode());\n}","preventionTips":["Never hand-edit or partially restore ACT_GE_BYTEARRAY rows; use deployment APIs.","Validate DB charset/encoding for blob columns during migrations.","Wrap readTree defensively when consuming blobs of uncertain provenance.","Re-save process definition info after upgrades or data restores."],"tags":["json","persistence","flowable","corrupt-data"],"backgroundTag":"invalid-json-response","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}