{"record":{"id":"87705957e3798ccb","repo":"flowable/flowable-engine","slug":"converter-can-only-convert-com-fasterxml-jackson-d","errorCode":null,"errorMessage":"Converter can only convert com.fasterxml.jackson.databind.JsonNode.","messagePattern":"Converter can only convert com\\.fasterxml\\.jackson\\.databind\\.JsonNode\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-common-rest/src/main/java/org/flowable/common/rest/variable/Jackson2JsonObjectRestVariableConverter.java","lineNumber":55,"sourceCode":"    public String getRestTypeName() {\n        return \"json\";\n    }\n\n    @Override\n    public Class<?> getVariableType() {\n        return JsonNode.class;\n    }\n\n    @Override\n    public Object getVariableValue(EngineRestVariable result) {\n        throw new UnsupportedOperationException(\"Cannot get variable value for jackson 2\");\n    }\n\n    @Override\n    public void convertVariableValue(Object variableValue, EngineRestVariable result) {\n        if (variableValue != null) {\n            if (!(variableValue instanceof JsonNode)) {\n                throw new FlowableIllegalArgumentException(\"Converter can only convert com.fasterxml.jackson.databind.JsonNode.\");\n            }\n            tools.jackson.databind.JsonNode valueNode = objectMapper.readTree(variableValue.toString());\n            result.setValue(valueNode);\n        } else {\n            result.setValue(null);\n        }\n    }\n\n}\n","sourceCodeStart":37,"sourceCodeEnd":65,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-common-rest/src/main/java/org/flowable/common/rest/variable/Jackson2JsonObjectRestVariableConverter.java#L37-L65","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nEngineRestVariable restVar = new EngineRestVariable();\nconverter.convertVariableValue(\"{\\\"a\\\":1}\", restVar);\n\n// after\nJsonNode node = objectMapper.readTree(\"{\\\"a\\\":1}\"); // com.fasterxml.jackson.databind.JsonNode\nconverter.convertVariableValue(node, restVar);","handlingStrategy":"type-guard","validationCode":"if (value instanceof com.fasterxml.jackson.databind.JsonNode node) {\n    converter.convertVariableValue(node, restVar);\n} else if (value != null) {\n    converter.convertVariableValue(objectMapper.readTree(value.toString()), restVar);\n}","typeGuard":"static boolean isJackson2JsonNode(Object v) {\n    return v instanceof com.fasterxml.jackson.databind.JsonNode;\n}","tryCatchPattern":"try {\n    converter.convertVariableValue(value, restVar);\n} catch (FlowableIllegalArgumentException e) {\n    throw new IllegalArgumentException(\"Expected a Jackson 2 JsonNode variable value, got: \"\n        + (value == null ? \"null\" : value.getClass().getName()), e);\n}","preventionTips":["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."],"tags":["jackson","rest-variable","type-mismatch","json"],"backgroundTag":"type-mismatch","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}