{"record":{"id":"58bb09ab5a620ba3","repo":"flowable/flowable-engine","slug":"json-string-does-not-represent-an-array","errorCode":null,"errorMessage":"JSON string does not represent an array: ","messagePattern":"JSON string does not represent an array: ","errorType":"validation","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/DefaultVariableValueConversionHandler.java","lineNumber":191,"sourceCode":"            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\n    /**\n     * Parses an ISO 8601 duration/period string (e.g. \"P10D\", \"PT10H\", \"P1Y2M3DT4H\") and adds it to the current time.\n     * Uses the same parsing logic as {@link org.flowable.common.engine.impl.calendar.DueDateBusinessCalendar}.\n     */\n    protected ZonedDateTime addDurationToNow(String durationString) {\n        ZonedDateTime now = ZonedDateTime.now();\n        Period period;\n        Duration duration;\n        if (durationString.startsWith(\"PT\")) {\n            period = Period.ZERO;\n            duration = Duration.parse(durationString);\n        } else {\n            int timeIndex = durationString.indexOf('T');\n            if (timeIndex > 0) {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/DefaultVariableValueConversionHandler.java#L173-L209","documentation":"convertToArray handles IO parameters declared as type 'array'. For String inputs it parses the string with the VariableJsonMapper and requires the resulting node to be a JSON array. If the parsed node is an object or scalar, Flowable throws this FlowableException echoing the string content.","triggerScenarios":"Binding a JSON string like '{\"a\":1}' or '\"text\"' to an 'array' IO parameter; a single element that was serialized as a bare object instead of wrapped in [ ... ].","commonSituations":"APIs returning a single object where callers expected a list and passed the string through unchanged; swapping 'json' and 'array' declarations in the model; hand-written default values in BPMN XML missing the surrounding brackets.","solutions":["Wrap the payload in a JSON array: '{\"a\":1}' -> '[{\"a\":1}]'.","If the value is an object, change the declared parameter type to 'json'.","Pass a Jackson ArrayNode directly instead of a String.","Pre-validate: JsonUtil.isArrayNode(mapper.readTree(s)) before binding."],"exampleFix":"// before\nexecution.setVariable(\"items\", \"{\\\"id\\\":1}\");\n// after\nexecution.setVariable(\"items\", \"[{\\\"id\\\":1}]\");","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.isArray()) {\n        throw new IllegalArgumentException(\"'array' parameter string must parse to a JSON array\");\n    }\n}","typeGuard":"static boolean isJsonArrayString(String s) {\n    String t = s == null ? \"\" : s.trim();\n    return t.startsWith(\"[\") && t.endsWith(\"]\");\n}","tryCatchPattern":"try {\n    Object arr = conversionHandler.convertValue(value, \"array\", mapper);\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"JSON string does not represent an array\")) { /* wrap in [...] or switch to 'json' type */ }\n    else throw e;\n}","preventionTips":["Wrap single objects in [ ... ] when the parameter is declared 'array'","Use 'json' declarations for object payloads","Pre-validate with JsonUtil.isArrayNode before binding strings"],"tags":["flowable","io-parameter","json","array","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"}