flowable/flowable-engine · error · FlowableException

JSON string does not represent an object:

Error message

JSON string does not represent an object: 

What it means

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.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/DefaultVariableValueConversionHandler.java:177

            String trimmed = stringValue.trim();
            if (trimmed.startsWith("P")) {
                return addDurationToNow(trimmed).toLocalDate();
            }
            return DateUtil.parseDate(trimmed).toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }
        throw new FlowableException("Cannot convert value of type " + value.getClass().getName() + " to LocalDate");
    }

    protected Object convertToJson(Object value, VariableJsonMapper variableJsonMapper) {
        if (value != null && JsonUtil.isObjectNode(value)) {
            return value;
        }
        if (value instanceof String stringValue) {
            Object jsonNode = variableJsonMapper.readTree(stringValue);
            if (JsonUtil.isObjectNode(jsonNode)) {
                return jsonNode;
            }
            throw new FlowableException("JSON string does not represent an object: " + stringValue);
        }
        throw new FlowableException("Cannot convert value of type " + value.getClass().getName() + " to JSON object");
    }

    protected Object convertToArray(Object value, VariableJsonMapper variableJsonMapper) {
        if (value != null && JsonUtil.isArrayNode(value)) {
            return value;
        }
        if (value instanceof String stringValue) {
            Object jsonNode = variableJsonMapper.readTree(stringValue);
            if (JsonUtil.isArrayNode(jsonNode)) {
                return jsonNode;
            }
            throw new FlowableException("JSON string does not represent an array: " + stringValue);
        }
        throw new FlowableException("Cannot convert value of type " + value.getClass().getName() + " to JSON array");
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Ensure the JSON string parses to an object: wrap arrays/scalars, e.g. '{"items":[1,2,3]}'.
  2. If the value is an array, declare the IO parameter type as 'array' instead of 'json'.
  3. Pass a Jackson ObjectNode directly instead of a String to avoid string parsing.
  4. Validate with JsonUtil/JsonMapper before binding: check isObjectNode(mapper.readTree(s)).

Example fix

// before
execution.setVariable("payload", "[1,2,3]");
// after
execution.setVariable("payload", "{\"items\":[1,2,3]}");
Defensive patterns

Strategy: validation

Validate before calling

if (value instanceof String s) {
    Object node = jsonMapper.readTree(s);
    if (!(node instanceof com.fasterxml.jackson.databind.JsonNode n) || !n.isObject()) {
        throw new IllegalArgumentException("'json' parameter string must parse to a JSON object");
    }
}

Type guard

static boolean isJsonObjectString(String s) {
    String t = s == null ? "" : s.trim();
    return t.startsWith("{") && t.endsWith("}");
}

Try / catch

try {
    Object json = conversionHandler.convertValue(value, "json", mapper);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("JSON string does not represent an object")) { /* wrap in object or switch to 'array' type */ }
    else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/0c827e5343e8ac8b. Report an issue: GitHub.