flowable/flowable-engine · error · FlowableException

Unable to serialize info node

Error message

Unable to serialize info node ${infoNode}

What it means

SaveProcessDefinitionInfoCmd.execute wraps any exception from Jackson serialization (or the DB update) in a FlowableException with message "Unable to serialize info node " + infoNode. This means the infoNode ObjectNode could not be converted to JSON bytes via the engine's ObjectMapper, or writing/persisting the resulting bytes failed.

Solutions

  1. Inspect the wrapped cause 'e' (getCause()) to see the actual Jackson/persistence failure.
  2. Ensure the info node contains only JSON-representable data; convert custom objects via objectMapper.valueToTree() first.
  3. Use the engine's ObjectMapper (processEngineConfiguration.getObjectMapper()) consistently rather than mixing mappers with different modules/configuration.

Example fix

// before
infoNode.putPOJO("handler", new MyNonSerializableHandler());
managementService.saveProcessDefinitionInfo(pdId, infoNode);
// after
JsonNode handlerNode = objectMapper.valueToTree(myHandler.toDto());
infoNode.set("handler", handlerNode);
managementService.saveProcessDefinitionInfo(pdId, infoNode);
Defensive patterns

Strategy: try-catch

Validate before calling

// validate node contents beforehand
if (infoNode == null || infoNode.isMissingNode()) {
    throw new IllegalArgumentException("infoNode must be a populated ObjectNode");
}
// dry-run serialize with the engine mapper
processEngineConfiguration.getObjectMapper().writeValueAsBytes(infoNode);

Try / catch

try {
    managementService.saveProcessDefinitionInfo(pdId, infoNode);
} catch (FlowableException e) {
    Throwable cause = e.getCause();
    log.error("Info node serialization failed: {}", cause != null ? cause.getMessage() : e.getMessage(), e);
    throw e;
}

Prevention

When it happens

Trigger: writer.writeValueAsBytes(infoNode) throws — e.g. a broken/cyclic node tree, custom value types inside the node the ObjectMapper cannot handle, or the updateInfoJson persistence call failing while the catch block covers the whole try.

Common situations: Custom ObjectMapper configuration on the process engine incompatible with the node contents; putting non-JSON-serializable objects into the node via putPOJO without matching serializers; serialization during a command whose DB context later rejects the write.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SaveProcessDefinitionInfoCmd.java:65

        }

        if (infoNode == null) {
            throw new FlowableIllegalArgumentException("process definition info node is null");
        }

        ProcessDefinitionInfoEntityManager definitionInfoEntityManager = CommandContextUtil.getProcessDefinitionInfoEntityManager(commandContext);
        ProcessDefinitionInfoEntity definitionInfoEntity = definitionInfoEntityManager.findProcessDefinitionInfoByProcessDefinitionId(processDefinitionId);
        if (definitionInfoEntity == null) {
            definitionInfoEntity = definitionInfoEntityManager.create();
            definitionInfoEntity.setProcessDefinitionId(processDefinitionId);
            CommandContextUtil.getProcessDefinitionInfoEntityManager().insertProcessDefinitionInfo(definitionInfoEntity);
        }

        try {
            ObjectWriter writer = CommandContextUtil.getProcessEngineConfiguration(commandContext).getObjectMapper().writer();
            CommandContextUtil.getProcessDefinitionInfoEntityManager().updateInfoJson(definitionInfoEntity.getId(), writer.writeValueAsBytes(infoNode));
        } catch (Exception e) {
            throw new FlowableException("Unable to serialize info node " + infoNode, e);
        }

        return null;
    }

}

View on GitHub (pinned to d6d39ce1c6)