{"record":{"id":"296e0f183adb01ad","repo":"flowable/flowable-engine","slug":"joining-scope-executions-is-not-allowed-296e0f","errorCode":null,"errorMessage":"joining scope executions is not allowed","messagePattern":"joining scope executions is not allowed","errorType":"exception","errorClass":"PvmException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/runtime/ExecutionImpl.java","lineNumber":641,"sourceCode":"            }\n        }\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"inactive concurrent executions in '{}': {}\", activity, inactiveConcurrentExecutionsInActivity);\n            LOGGER.debug(\"other concurrent executions: {}\", otherConcurrentExecutions);\n        }\n        return inactiveConcurrentExecutionsInActivity;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public void takeAll(List<PvmTransition> transitions, List<ActivityExecution> recyclableExecutions) {\n        transitions = new ArrayList<>(transitions);\n        recyclableExecutions = (recyclableExecutions != null ? new ArrayList<>(recyclableExecutions) : new ArrayList<>());\n\n        if (recyclableExecutions.size() > 1) {\n            for (ActivityExecution recyclableExecution : recyclableExecutions) {\n                if (((ExecutionImpl) recyclableExecution).isScope()) {\n                    throw new PvmException(\"joining scope executions is not allowed\");\n                }\n            }\n        }\n\n        ExecutionImpl concurrentRoot = ((isConcurrent && !isScope) ? getParent() : this);\n        List<ExecutionImpl> concurrentActiveExecutions = new ArrayList<>();\n        for (ExecutionImpl execution : concurrentRoot.getExecutions()) {\n            if (execution.isActive()) {\n                concurrentActiveExecutions.add(execution);\n            }\n        }\n\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"transitions to take concurrent: {}\", transitions);\n            LOGGER.debug(\"active concurrent executions: {}\", concurrentActiveExecutions);\n        }\n\n        if ((transitions.size() == 1)","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/pvm/runtime/ExecutionImpl.java#L623-L659","documentation":"A PvmException thrown by ExecutionImpl.takeAll when more than one execution is being recycled/joined at an activity and at least one of them is a scope execution. Scope executions (e.g. those owning process/scope variables or sub-scopes) may not be joined together. This guards the execution-tree scope invariants during concurrent join (e.g. parallel gateway merge).","triggerScenarios":"takeAll() called with multiple recyclable executions where isScope() is true for one of them — typically from custom concurrency behaviors attempting to join executions that own scopes (embedded sub-process scope roots) instead of leaf concurrent executions.","commonSituations":"Custom join/merge behaviors incorrectly recycling scope-rooted executions; modeling constructs that fork inside an embedded sub-process and join at scope level; engine-version migrations where scope semantics changed.","solutions":["Redesign the custom join behavior to only recycle non-scope concurrent (leaf) executions","Move the join out of the sub-process scope so participating executions are not scope roots","Use the engine's built-in parallel/inclusive gateway instead of custom takeAll logic","Check whether the joined executions became scopes due to async boundaries/event scopes and adjust the model"],"exampleFix":"// before\nList<ActivityExecution> joined = executions.stream()\n    .filter(e -> ((ExecutionImpl) e).isScope() || true) // recycles scopes too\n    .collect(toList());\ntakeAll(joined, null);\n// after\nList<ActivityExecution> leaves = executions.stream()\n    .filter(e -> !((ExecutionImpl) e).isScope())\n    .collect(toList());\ntakeAll(leaves, null);","handlingStrategy":"validation","validationCode":"// before takeAll, verify no recyclable execution is a scope\nboolean scopeJoin = recyclable.stream().anyMatch(e -> ((ExecutionImpl) e).isScope());\nif (scopeJoin) throw new ActivitiException(\"cannot join scope executions\");","typeGuard":"boolean isLeaf(PvmExecution e) { return e instanceof ExecutionImpl && !((ExecutionImpl) e).isScope(); }","tryCatchPattern":"try {\n  customJoin.executions(recyclable);\n} catch (PvmException e) {\n  if (e.getMessage().contains(\"joining scope executions\")) { /* redesign join */ }\n}","preventionTips":["Only recycle non-scope concurrent executions in custom joins","Prefer standard parallel gateway merge semantics","Review scope roots when forking inside embedded sub-processes"],"tags":["process-engine","concurrency","scope"],"backgroundTag":"invalid-state-transition","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"}