{"record":{"id":"1e6eba15ffafe833","repo":"Activiti/Activiti","slug":"no-sub-process-execution-found-for-cancel-end-even","errorCode":null,"errorMessage":"No sub process execution found for cancel end event ","messagePattern":"No sub process execution found for cancel end event ","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java","lineNumber":68,"sourceCode":"        ExecutionEntity currentlyExaminedExecution = executionEntityManager.findById(executionEntity.getParentId());\n        while (currentlyExaminedExecution != null && parentScopeExecution == null) {\n            if (currentlyExaminedExecution.getCurrentFlowElement() instanceof SubProcess) {\n                parentScopeExecution = currentlyExaminedExecution;\n                SubProcess subProcess = (SubProcess) currentlyExaminedExecution.getCurrentFlowElement();\n                if (subProcess.getLoopCharacteristics() != null) {\n                    ExecutionEntity miExecution = parentScopeExecution.getParent();\n                    FlowElement miElement = miExecution.getCurrentFlowElement();\n                    if (miElement != null && miElement.getId().equals(subProcess.getId())) {\n                        parentScopeExecution = miExecution;\n                    }\n                }\n            } else {\n                currentlyExaminedExecution = executionEntityManager.findById(currentlyExaminedExecution.getParentId());\n            }\n        }\n\n        if (parentScopeExecution == null) {\n            throw new ActivitiException(\n                \"No sub process execution found for cancel end event \" + executionEntity.getCurrentActivityId()\n            );\n        }\n\n        SubProcess subProcess = (SubProcess) parentScopeExecution.getCurrentFlowElement();\n        BoundaryEvent cancelBoundaryEvent = null;\n        if (CollectionUtil.isNotEmpty(subProcess.getBoundaryEvents())) {\n            for (BoundaryEvent boundaryEvent : subProcess.getBoundaryEvents()) {\n                if (\n                    CollectionUtil.isNotEmpty(boundaryEvent.getEventDefinitions()) &&\n                    boundaryEvent.getEventDefinitions().getFirst() instanceof CancelEventDefinition\n                ) {\n                    cancelBoundaryEvent = boundaryEvent;\n                    break;\n                }\n            }\n        }\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/Activiti/Activiti/blob/56435b1a97deeafdc09dd40074b056c89fba5a8a/activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java#L50-L86","documentation":"Thrown by CancelEndEventActivityBehavior.execute when a cancel end event cannot find the enclosing sub-process scope execution it must cancel. The behavior walks up the execution tree looking for the scope that contains a transaction, and if it never finds a parent scope execution it fails. Cancel end events are only valid inside a transactional sub-process with a cancel boundary event.","triggerScenarios":"A <cancelEndEvent> is reached but the execution tree has no parent scope execution matching the transaction sub-process — e.g. cancel end event placed outside a transaction sub-process or model/config corruption removed the scope execution.","commonSituations":"BPMN modeling mistake: cancel end event in a regular (non-transaction) sub-process or at process level; historic process instances with modified executions after a DB migration or manual cleanup between Activiti versions.","solutions":["Move the cancel end event inside a <transaction subProcess> that has a cancel boundary event attached.","Validate the BPMN model (activiti-modeler/validation) so cancel events only appear in transaction sub-processes.","Check the execution tree in ACT_RU_EXECUTION for missing/damaged scope executions; restart the instance from a known-good state.","Replace the cancel end event with an error end event + error boundary if transactional rollback semantics are not required."],"exampleFix":"<!-- before -->\n<subProcess id=\"sp\"><endEvent id=\"e\"><cancelEventDefinition/></endEvent></subProcess>\n<!-- after -->\n<transaction id=\"tx\"><endEvent id=\"e\"><cancelEventDefinition/></endEvent></transaction>\n<boundaryEvent id=\"cancelB\" attachedToRef=\"tx\"><cancelEventDefinition/></boundaryEvent>","handlingStrategy":"validation","validationCode":"// At deploy time: validate cancel end events are only inside <transaction> sub-processes\nif (!\"transaction\".equals(parentElement.getType())) {\n    throw new IllegalArgumentException(\"cancelEndEvent must be inside a transaction subProcess\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    processEngine.getRuntimeService().signal(executionId);\n} catch (ActivitiException e) {\n    if (e.getMessage().startsWith(\"No sub process execution found\")) {\n        // model error: redeploy corrected definition\n    }\n}","preventionTips":["Run BPMN model validation before every deployment.","Only place cancel end events inside transaction sub-processes.","Prefer error end events when rollback semantics are not needed."],"tags":["activiti","bpmn","cancel-end-event","subprocess","modeling"],"backgroundTag":"invalid-state-transition","analyzedSha":"56435b1a97deeafdc09dd40074b056c89fba5a8a","analyzedAt":"2026-09-09T21:00:06.703Z","contentChangedAt":"2026-09-09T21:00:06.703Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}