{"record":{"id":"4a0f86bc0a12d766","repo":"flowable/flowable-engine","slug":"cannot-aggregate-overview-variable-varinstance-4a0f86","errorCode":null,"errorMessage":"Cannot aggregate overview variable: ${varInstance}","messagePattern":"Cannot aggregate overview variable: (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/delegate/JsonVariableAggregator.java","lineNumber":160,"sourceCode":"                        case LocalDateType.TYPE_NAME:\n                        case LocalDateTimeType.TYPE_NAME:\n                        case JodaDateType.TYPE_NAME:\n                        case JodaDateTimeType.TYPE_NAME:\n                        case UUIDType.TYPE_NAME:\n                            // For all these types it is OK to use toString as their string representation is what we want to have\n                            objectNode.put(targetVarName, varInstance.getValue().toString());\n                            break;\n                        case ByteArrayType.TYPE_NAME:\n                            objectNode.put(targetVarName, (byte[]) varInstance.getValue());\n                            break;\n                        default:\n                            if (VariableAggregatorContext.OVERVIEW.equals(context.getState())) {\n                                // We can only use the aggregated variable if we are in an overview state\n                                Object value = varInstance.getValue();\n                                if (jsonMapper.isJsonNode(value)) {\n                                    objectNode.set(targetVarName, JsonUtil.asFlowableJsonNode(value));\n                                } else {\n                                    throw new FlowableException(\"Cannot aggregate overview variable: \" + varInstance);\n                                }\n                            } else {\n                                throw new FlowableException(\"Cannot aggregate variable: \" + varInstance);\n                            }\n                    }\n                }\n\n            }\n        }\n\n        return objectNode.getImplementationValue();\n    }\n\n    @Override\n    public Object aggregateMultiVariables(DelegateExecution execution, List<? extends VariableInstance> instances, VariableAggregatorContext context) {\n        VariableJsonMapper objectMapper = processEngineConfiguration.getVariableJsonMapper();\n        FlowableArrayNode arrayNode = objectMapper.createArrayNode();\n        for (VariableInstance instance : instances) {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/delegate/JsonVariableAggregator.java#L142-L178","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure all variables targeted for aggregation are stored as JSON (set them as JSON strings/nodes via JsonUtil or the flowable JSON variable type)","Check the ProcessEngineConfiguration's JsonMapper / variable type configuration so JSON variables are recognized by isJsonNode","Exclude non-JSON variables from the aggregation target variable name (targetVarName) so the aggregator never sees them","Add a conversion step in the delegate to serialize the value into a Flowable JSON node before storing it"],"exampleFix":"// before\nexecution.setVariable(\"childResult\", new MyPojo());\n// after\nexecution.setVariable(\"childResult\",\n    JsonUtil.getFlowableJsonNode(objectMapper.valueToTree(new MyPojo())));","handlingStrategy":"type-guard","validationCode":"Object v = execution.getVariable(\"childResult\");\nif (!(v instanceof JsonNode) && !(v instanceof String && looksLikeJson((String) v))) {\n    throw new IllegalStateException(\"Variable must be JSON for aggregation\");\n}","typeGuard":"boolean isJsonVariable(Object v) {\n    return v instanceof com.fasterxml.jackson.databind.JsonNode;\n}","tryCatchPattern":"try {\n    aggregated = aggregator.aggregateSingleVariable(ctx, varInstances);\n} catch (FlowableException e) {\n    logger.error(\"Non-JSON variable in aggregation: \" + e.getMessage(), e);\n}","preventionTips":["Set variables intended for aggregation via JsonUtil helpers","Keep the engine's JsonMapper configuration consistent","Restrict aggregation to a known set of JSON-typed variables"],"tags":["variables","json","aggregation"],"backgroundTag":"incompatible-source-type","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}