flowable/flowable-engine · error · FlowableException

Cannot aggregate overview variable

Error message

Cannot aggregate overview variable: ${varInstance}

What it means

JsonVariableAggregator.aggregateSingleVariable merges variable instances into a JSON object. In OVERVIEW state it can only include values that are JSON nodes; when a variable instance's value is not recognized as a JSON node (per the configured JsonMapper) it throws this exception instead of silently aggregating it.

Solutions

  1. Ensure all variables targeted for aggregation are stored as JSON (set them as JSON strings/nodes via JsonUtil or the flowable JSON variable type)
  2. Check the ProcessEngineConfiguration's JsonMapper / variable type configuration so JSON variables are recognized by isJsonNode
  3. Exclude non-JSON variables from the aggregation target variable name (targetVarName) so the aggregator never sees them
  4. Add a conversion step in the delegate to serialize the value into a Flowable JSON node before storing it

Example fix

// before
execution.setVariable("childResult", new MyPojo());
// after
execution.setVariable("childResult",
    JsonUtil.getFlowableJsonNode(objectMapper.valueToTree(new MyPojo())));
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = execution.getVariable("childResult");
if (!(v instanceof JsonNode) && !(v instanceof String && looksLikeJson((String) v))) {
    throw new IllegalStateException("Variable must be JSON for aggregation");
}

Type guard

boolean isJsonVariable(Object v) {
    return v instanceof com.fasterxml.jackson.databind.JsonNode;
}

Try / catch

try {
    aggregated = aggregator.aggregateSingleVariable(ctx, varInstances);
} catch (FlowableException e) {
    logger.error("Non-JSON variable in aggregation: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Overview aggregation (e.g. root-process overview variables created by JsonChildProcessVariableAggregator-style flows) encountering a child-process variable whose value is a plain object (String, POJO, byte[]) rather than a JSON node.

Common situations: Process variables set via Java delegates to non-JSON types while parallel multi-instance child processes aggregate them into a parent overview variable; mixing serializedValueTypes so some variables come back as non-JSON.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/delegate/JsonVariableAggregator.java:160

                        case LocalDateType.TYPE_NAME:
                        case LocalDateTimeType.TYPE_NAME:
                        case JodaDateType.TYPE_NAME:
                        case JodaDateTimeType.TYPE_NAME:
                        case UUIDType.TYPE_NAME:
                            // For all these types it is OK to use toString as their string representation is what we want to have
                            objectNode.put(targetVarName, varInstance.getValue().toString());
                            break;
                        case ByteArrayType.TYPE_NAME:
                            objectNode.put(targetVarName, (byte[]) varInstance.getValue());
                            break;
                        default:
                            if (VariableAggregatorContext.OVERVIEW.equals(context.getState())) {
                                // We can only use the aggregated variable if we are in an overview state
                                Object value = varInstance.getValue();
                                if (jsonMapper.isJsonNode(value)) {
                                    objectNode.set(targetVarName, JsonUtil.asFlowableJsonNode(value));
                                } else {
                                    throw new FlowableException("Cannot aggregate overview variable: " + varInstance);
                                }
                            } else {
                                throw new FlowableException("Cannot aggregate variable: " + varInstance);
                            }
                    }
                }

            }
        }

        return objectNode.getImplementationValue();
    }

    @Override
    public Object aggregateMultiVariables(DelegateExecution execution, List<? extends VariableInstance> instances, VariableAggregatorContext context) {
        VariableJsonMapper objectMapper = processEngineConfiguration.getVariableJsonMapper();
        FlowableArrayNode arrayNode = objectMapper.createArrayNode();
        for (VariableInstance instance : instances) {

View on GitHub (pinned to d6d39ce1c6)