{"record":{"id":"0c827e5343e8ac8b","repo":"flowable/flowable-engine","slug":"json-string-does-not-represent-an-object","errorCode":null,"errorMessage":"JSON string does not represent an object: ","messagePattern":"JSON string does not represent an object: ","errorType":"validation","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/DefaultVariableValueConversionHandler.java","lineNumber":177,"sourceCode":"            String trimmed = stringValue.trim();\n            if (trimmed.startsWith(\"P\")) {\n                return addDurationToNow(trimmed).toLocalDate();\n            }\n            return DateUtil.parseDate(trimmed).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();\n        }\n        throw new FlowableException(\"Cannot convert value of type \" + value.getClass().getName() + \" to LocalDate\");\n    }\n\n    protected Object convertToJson(Object value, VariableJsonMapper variableJsonMapper) {\n        if (value != null && JsonUtil.isObjectNode(value)) {\n            return value;\n        }\n        if (value instanceof String stringValue) {\n            Object jsonNode = variableJsonMapper.readTree(stringValue);\n            if (JsonUtil.isObjectNode(jsonNode)) {\n                return jsonNode;\n            }\n            throw new FlowableException(\"JSON string does not represent an object: \" + stringValue);\n        }\n        throw new FlowableException(\"Cannot convert value of type \" + value.getClass().getName() + \" to JSON object\");\n    }\n\n    protected Object convertToArray(Object value, VariableJsonMapper variableJsonMapper) {\n        if (value != null && JsonUtil.isArrayNode(value)) {\n            return value;\n        }\n        if (value instanceof String stringValue) {\n            Object jsonNode = variableJsonMapper.readTree(stringValue);\n            if (JsonUtil.isArrayNode(jsonNode)) {\n                return jsonNode;\n            }\n            throw new FlowableException(\"JSON string does not represent an array: \" + stringValue);\n        }\n        throw new FlowableException(\"Cannot convert value of type \" + value.getClass().getName() + \" to JSON array\");\n    }\n","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/DefaultVariableValueConversionHandler.java#L159-L195","documentation":"convertToJson handles IO parameters declared as type 'json'. When given a String, it parses the string via the configured VariableJsonMapper (readTree) and requires the resulting node to be a JSON object. If the parsed node is an array, scalar, or other non-object node, Flowable throws this FlowableException echoing the offending string.","triggerScenarios":"Binding a JSON string like '[1,2,3]' or '\"text\"' or '42' to a 'json' IO parameter declared to hold an object; an upstream API returns a top-level array serialized to a string that is then bound as the parameter value.","commonSituations":"REST payloads where the top level is an array being forwarded into a process variable; config mistakes where the 'json' parameter was meant to be 'array'; double-serialized strings ('\"{\\\"a\\\":1}\"') parsing to a textual node.","solutions":["Ensure the JSON string parses to an object: wrap arrays/scalars, e.g. '{\"items\":[1,2,3]}'.","If the value is an array, declare the IO parameter type as 'array' instead of 'json'.","Pass a Jackson ObjectNode directly instead of a String to avoid string parsing.","Validate with JsonUtil/JsonMapper before binding: check isObjectNode(mapper.readTree(s))."],"exampleFix":"// before\nexecution.setVariable(\"payload\", \"[1,2,3]\");\n// after\nexecution.setVariable(\"payload\", \"{\\\"items\\\":[1,2,3]}\");","handlingStrategy":"validation","validationCode":"if (value instanceof String s) {\n    Object node = jsonMapper.readTree(s);\n    if (!(node instanceof com.fasterxml.jackson.databind.JsonNode n) || !n.isObject()) {\n        throw new IllegalArgumentException(\"'json' parameter string must parse to a JSON object\");\n    }\n}","typeGuard":"static boolean isJsonObjectString(String s) {\n    String t = s == null ? \"\" : s.trim();\n    return t.startsWith(\"{\") && t.endsWith(\"}\");\n}","tryCatchPattern":"try {\n    Object json = conversionHandler.convertValue(value, \"json\", mapper);\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"JSON string does not represent an object\")) { /* wrap in object or switch to 'array' type */ }\n    else throw e;\n}","preventionTips":["Check whether upstream payloads are top-level arrays and route them to 'array' parameters","Avoid double-serializing JSON (string containing an escaped string)","Validate JSON shape with a schema before binding to process variables"],"tags":["flowable","io-parameter","json","shape-mismatch"],"backgroundTag":"schema-validation-failed","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"}