{"record":{"id":"d47b47b241a5553f","repo":"flowable/flowable-engine","slug":"converter-can-only-convert-tools-jackson-databind","errorCode":null,"errorMessage":"Converter can only convert tools.jackson.databind.JsonNode.","messagePattern":"Converter can only convert tools\\.jackson\\.databind\\.JsonNode\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-common-rest/src/main/java/org/flowable/common/rest/variable/JsonObjectRestVariableConverter.java","lineNumber":61,"sourceCode":"    public Object getVariableValue(EngineRestVariable result) {\n        if (result.getValue() != null) {\n            if (result.getValue() instanceof Map || result.getValue() instanceof List) {\n                // When the variable is coming from the REST API it automatically gets converted to an ArrayList or\n                // LinkedHashMap. In all other cases JSON is saved as ArrayNode or ObjectNode. For consistency the\n                // variable is converted to such an object here.\n                return objectMapper.valueToTree(result.getValue());\n            } else {\n                return result.getValue();\n            }\n        }\n        return null;\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 tools.jackson.databind.JsonNode.\");\n            }\n            result.setValue(variableValue);\n        } else {\n            result.setValue(null);\n        }\n    }\n\n}\n","sourceCodeStart":43,"sourceCodeEnd":70,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-common-rest/src/main/java/org/flowable/common/rest/variable/JsonObjectRestVariableConverter.java#L43-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncom.fasterxml.jackson.databind.JsonNode oldNode = oldMapper.valueToTree(map);\nconverter.convertVariableValue(oldNode, restVar); // throws\n\n// after\ntools.jackson.databind.JsonNode node = toolsJacksonMapper.valueToTree(map);\nconverter.convertVariableValue(node, restVar);","handlingStrategy":"type-guard","validationCode":"if (value instanceof tools.jackson.databind.JsonNode node) {\n    converter.convertVariableValue(node, restVar);\n} else {\n    converter.convertVariableValue(toolsJacksonMapper.valueToTree(value), restVar);\n}","typeGuard":"static boolean isJackson3JsonNode(Object v) {\n    return v instanceof tools.jackson.databind.JsonNode;\n}","tryCatchPattern":"try {\n    converter.convertVariableValue(value, restVar);\n} catch (FlowableIllegalArgumentException e) {\n    throw new IllegalArgumentException(\"Expected a tools.jackson JsonNode, got: \"\n        + (value == null ? \"null\" : value.getClass().getName()), e);\n}","preventionTips":["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."],"tags":["jackson3","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-14T05:17:10.506Z"}