flowable/flowable-engine · error · FlowableIllegalArgumentException
Converter can only convert com.fasterxml.jackson.databind.Js
Error message
Converter can only convert com.fasterxml.jackson.databind.JsonNode.
What it means
Jackson2JsonObjectRestVariableConverter.convertVariableValue only accepts com.fasterxml.jackson.databind.JsonNode values when serializing an engine variable to a REST variable. If the supplied object is any other type, it throws FlowableIllegalArgumentException because the converter's contract is exclusively JsonNode-to-REST. Note the snippet then calls tools.jackson readTree, indicating a Jackson 2/3 migration inconsistency: the instanceof check guards the Jackson 2 type while downstream code targets tools.jackson (Jackson 3).
Source
Thrown at modules/flowable-common-rest/src/main/java/org/flowable/common/rest/variable/Jackson2JsonObjectRestVariableConverter.java:55
public String getRestTypeName() {
return "json";
}
@Override
public Class<?> getVariableType() {
return JsonNode.class;
}
@Override
public Object getVariableValue(EngineRestVariable result) {
throw new UnsupportedOperationException("Cannot get variable value for jackson 2");
}
@Override
public void convertVariableValue(Object variableValue, EngineRestVariable result) {
if (variableValue != null) {
if (!(variableValue instanceof JsonNode)) {
throw new FlowableIllegalArgumentException("Converter can only convert com.fasterxml.jackson.databind.JsonNode.");
}
tools.jackson.databind.JsonNode valueNode = objectMapper.readTree(variableValue.toString());
result.setValue(valueNode);
} else {
result.setValue(null);
}
}
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Ensure the variable value passed in is a com.fasterxml.jackson.databind.JsonNode built with the same ObjectMapper instance the converter uses.
- If migrating to tools.jackson (Jackson 3), use JsonObjectRestVariableConverter instead, or update the instanceof check and imports to the same Jackson flavor used downstream.
- Remove duplicate/old Jackson versions from the classpath so both the converter and callers agree on one Jackson.
- If the value is a String or Map, parse it first (objectMapper.readTree / valueToTree) before handing it to the converter.
Example fix
// before
EngineRestVariable restVar = new EngineRestVariable();
converter.convertVariableValue("{\"a\":1}", restVar);
// after
JsonNode node = objectMapper.readTree("{\"a\":1}"); // com.fasterxml.jackson.databind.JsonNode
converter.convertVariableValue(node, restVar); Defensive patterns
Strategy: type-guard
Validate before calling
if (value instanceof com.fasterxml.jackson.databind.JsonNode node) {
converter.convertVariableValue(node, restVar);
} else if (value != null) {
converter.convertVariableValue(objectMapper.readTree(value.toString()), restVar);
} Type guard
static boolean isJackson2JsonNode(Object v) {
return v instanceof com.fasterxml.jackson.databind.JsonNode;
} Try / catch
try {
converter.convertVariableValue(value, restVar);
} catch (FlowableIllegalArgumentException e) {
throw new IllegalArgumentException("Expected a Jackson 2 JsonNode variable value, got: "
+ (value == null ? "null" : value.getClass().getName()), e);
} Prevention
- Pin a single Jackson generation (2 vs tools.jackson) across the project and converters.
- Build variable values with the same ObjectMapper instance used by the REST layer.
- Add a unit test per REST variable type covering its converter round-trip.
When it happens
Trigger: Calling convertVariableValue(variableValue, result) with a non-null object that is not a com.fasterxml.jackson.databind.JsonNode (e.g. a String, Map, ObjectNode from tools.jackson, or a POJO), typically via REST variable serialization when the variable's Java type was resolved to this converter.
Common situations: Mixed Jackson versions on the classpath during a Jackson 2 to Jackson 3 (tools.jackson) migration: code builds an ObjectNode with one Jackson but the converter checks the other. Also passing raw JSON strings or Maps instead of a parsed JsonNode.
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 tools.jackson.databind.JsonNode.
- Unsupported value type ${value == null ? "null" : value.getC
- Unsupported value type " + (value == null ? "null" : value.g
- Cannot convert value of type ${value.getClass()} to Jackson
- Error writing form model response
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/87705957e3798ccb.
Report an issue: GitHub.