flowable/flowable-engine · error · FlowableException

Error reading json info node for process definition " +…

Error message

Error reading json info node for process definition " + processDefinitionId

What it means

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.

Solutions

  1. 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).
  2. 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.
  3. Check database charset/encoding settings for the blob column; fix mismatched encoding and re-write the bytes.
  4. 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.

Example fix

// before (corrupt blob parsed blindly)
byte[] infoBytes = infoEntityManager.findInfoJsonById(infoEntity.getInfoJsonId());
ObjectNode infoNode = (ObjectNode) objectMapper.readTree(infoBytes);
// after (caller-side guard + repair path)
byte[] infoBytes = infoEntityManager.findInfoJsonById(infoEntity.getInfoJsonId());
JsonNode raw = objectMapper.readTree(infoBytes);
if (raw == null || !raw.isObject()) {
    // fall back to empty info node and re-publish definition info
    cacheObject.setInfoNode(objectMapper.createObjectNode());
} else {
    cacheObject.setInfoNode((ObjectNode) raw);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Java: validate blob before use
JsonNode check(byte[] bytes, ObjectMapper om) {
    try { return om.readTree(bytes); } catch (Exception e) { return null; }
}

Type guard

boolean isValidInfoJson(JsonNode n) { return n != null && n.isObject(); }

Try / catch

try {
    ObjectNode node = (ObjectNode) objectMapper.readTree(infoBytes);
    cacheObject.setInfoNode(node);
} catch (FlowableException e) {
    // inspect/repair ACT_GE_BYTEARRAY row or fall back to empty node
    cacheObject.setInfoNode(objectMapper.createObjectNode());
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/0f3876c831793795. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/persistence/deploy/ProcessDefinitionInfoCache.java:148

        ProcessDefinitionInfoCacheObject cacheObject = null;
        if (cache.containsKey(processDefinitionId)) {
            cacheObject = cache.get(processDefinitionId);
        } else {
            cacheObject = new ProcessDefinitionInfoCacheObject();
            cacheObject.setRevision(0);
            cacheObject.setInfoNode(objectMapper.createObjectNode());
        }

        ProcessDefinitionInfoEntity infoEntity = infoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId);
        if (infoEntity != null && infoEntity.getRevision() != cacheObject.getRevision()) {
            cacheObject.setRevision(infoEntity.getRevision());
            if (infoEntity.getInfoJsonId() != null) {
                byte[] infoBytes = infoEntityManager.findInfoJsonById(infoEntity.getInfoJsonId());
                try {
                    ObjectNode infoNode = (ObjectNode) objectMapper.readTree(infoBytes);
                    cacheObject.setInfoNode(infoNode);
                } catch (Exception e) {
                    throw new FlowableException("Error reading json info node for process definition " + processDefinitionId, e);
                }
            }
        } else if (infoEntity == null) {
            cacheObject.setRevision(0);
            cacheObject.setInfoNode(objectMapper.createObjectNode());
        }

        return cacheObject;
    }

}

View on GitHub (pinned to d6d39ce1c6)