flowable/flowable-engine · error · FlowableIllegalArgumentException
Converter can only convert tools.jackson.databind.JsonNode.
Error message
Converter can only convert tools.jackson.databind.JsonNode.
What it means
JsonObjectRestVariableConverter.convertVariableValue only accepts tools.jackson.databind.JsonNode (Jackson 3) values when writing an engine variable to an EngineRestVariable. Any other non-null object type fails the instanceof guard and throws FlowableIllegalArgumentException, since this converter deliberately targets the new tools.jackson API.
Source
Thrown at modules/flowable-common-rest/src/main/java/org/flowable/common/rest/variable/JsonObjectRestVariableConverter.java:61
public Object getVariableValue(EngineRestVariable result) {
if (result.getValue() != null) {
if (result.getValue() instanceof Map || result.getValue() instanceof List) {
// When the variable is coming from the REST API it automatically gets converted to an ArrayList or
// LinkedHashMap. In all other cases JSON is saved as ArrayNode or ObjectNode. For consistency the
// variable is converted to such an object here.
return objectMapper.valueToTree(result.getValue());
} else {
return result.getValue();
}
}
return null;
}
@Override
public void convertVariableValue(Object variableValue, EngineRestVariable result) {
if (variableValue != null) {
if (!(variableValue instanceof JsonNode)) {
throw new FlowableIllegalArgumentException("Converter can only convert tools.jackson.databind.JsonNode.");
}
result.setValue(variableValue);
} else {
result.setValue(null);
}
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Build the value with tools.jackson JsonMapper/JsonNode so the instanceof check passes.
- If you only have a Jackson 2 JsonNode, convert it (e.g. via its toString() parsed by tools.jackson readTree) or use Jackson2JsonObjectRestVariableConverter.
- Unify the classpath on a single Jackson generation to avoid cross-API node types.
- Parse Strings/Maps into a tools.jackson JsonNode before calling the converter.
Example fix
// before com.fasterxml.jackson.databind.JsonNode oldNode = oldMapper.valueToTree(map); converter.convertVariableValue(oldNode, restVar); // throws // after tools.jackson.databind.JsonNode node = toolsJacksonMapper.valueToTree(map); converter.convertVariableValue(node, restVar);
Defensive patterns
Strategy: type-guard
Validate before calling
if (value instanceof tools.jackson.databind.JsonNode node) {
converter.convertVariableValue(node, restVar);
} else {
converter.convertVariableValue(toolsJacksonMapper.valueToTree(value), restVar);
} Type guard
static boolean isJackson3JsonNode(Object v) {
return v instanceof tools.jackson.databind.JsonNode;
} Try / catch
try {
converter.convertVariableValue(value, restVar);
} catch (FlowableIllegalArgumentException e) {
throw new IllegalArgumentException("Expected a tools.jackson JsonNode, got: "
+ (value == null ? "null" : value.getClass().getName()), e);
} Prevention
- During Jackson 2 -> 3 migration, grep for com.fasterxml node construction and convert to tools.jackson.
- Normalize any incoming value via mapper.valueToTree before calling the converter.
- Keep one JsonMapper bean injected everywhere instead of ad-hoc node construction.
When it happens
Trigger: Passing a non-null object that is not a tools.jackson.databind.JsonNode (e.g. a com.fasterxml.jackson.databind.JsonNode from Jackson 2, a String, or a Map) into convertVariableValue, typically during REST variable serialization.
Common situations: Jackson 2 to Jackson 3 migration where callers still construct nodes with the old com.fasterxml API; mixing both Jacksons on the classpath; passing pre-serialized JSON strings instead of parsed nodes.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Converter can only convert com.fasterxml.jackson.databind.Js
- Converter can only convert string to localDate
- Converter can only convert localDate
- Converter can only convert string to localDateTime
- Converter can only convert localDateTime
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/d47b47b241a5553f.
Report an issue: GitHub.