{"record":{"id":"2565a08ed5729bf8","repo":"flowable/flowable-engine","slug":"could-not-find-cancel-boundary-event-for-cancel-en-2565a0","errorCode":null,"errorMessage":"Could not find cancel boundary event for cancel end event ${activity}","messagePattern":"Could not find cancel boundary event for cancel end event (.+?)","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java","lineNumber":38,"sourceCode":"import org.activiti.engine.impl.pvm.process.ActivityImpl;\r\nimport org.activiti.engine.impl.pvm.runtime.InterpretableExecution;\r\nimport org.flowable.engine.delegate.DelegateExecution;\r\n\r\n/**\r\n * @author Daniel Meyer\r\n * @author Falko Menge\r\n */\r\npublic class CancelEndEventActivityBehavior extends FlowNodeActivityBehavior {\r\n\r\n    @Override\r\n    public void execute(DelegateExecution execution) {\r\n        ActivityExecution activityExecution = (ActivityExecution) execution;\r\n        // find cancel boundary event:\r\n        ActivityImpl cancelBoundaryEvent = ScopeUtil\r\n                .findInParentScopesByBehaviorType((ActivityImpl) activityExecution.getActivity(), CancelBoundaryEventActivityBehavior.class);\r\n\r\n        if (cancelBoundaryEvent == null) {\r\n            throw new ActivitiException(\"Could not find cancel boundary event for cancel end event \" + activityExecution.getActivity());\r\n        }\r\n\r\n        ActivityExecution scopeExecution = ScopeUtil.findScopeExecutionForScope((ExecutionEntity) execution, cancelBoundaryEvent.getParentActivity());\r\n\r\n        // end all executions and process instances in the scope of the transaction\r\n        scopeExecution.destroyScope(\"cancel end event fired\");\r\n\r\n        // the scope execution executes the boundary event\r\n        InterpretableExecution outgoingExecution = (InterpretableExecution) scopeExecution;\r\n        outgoingExecution.setActivity(cancelBoundaryEvent);\r\n        outgoingExecution.setActive(true);\r\n\r\n        // execute the boundary\r\n        cancelBoundaryEvent\r\n                .getActivityBehavior()\r\n                .execute(outgoingExecution);\r\n    }\r\n\r","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java#L20-L56","documentation":"CancelEndEventActivityBehavior.execute() searches the activity's parent scopes for a cancel boundary event attached to the enclosing transaction subprocess. If none exists, the cancel end event was modeled outside a transaction subprocess with a compensating cancel boundary, so it throws ActivitiException.","triggerScenarios":"A cancel end event is placed inside a subprocess that is not a transaction subprocess, or the transaction subprocess has no cancel boundary event attached, and execution reaches the cancel end event.","commonSituations":"Mis-modeled BPMN: cancel end event used outside transaction/cancel-boundary context; a model copied from another diagram where the boundary event was deleted.","solutions":["Place the cancel end event inside a transaction subprocess and attach a cancel boundary event to that transaction","Remove the cancel end event and use a plain end event if transaction rollback semantics are not intended","Validate the BPMN model at deploy time to catch illegal cancel end event usage"],"exampleFix":"// before\n<subProcess id=\"sp\"><endEvent id=\"cancelEnd\"><cancelEventDefinition/></endEvent></subProcess>\n// after\n<transaction id=\"tx\">\n  <endEvent id=\"cancelEnd\"><cancelEventDefinition/></endEvent>\n</transaction>\n<boundaryEvent id=\"cancelBoundary\" attachedToRef=\"tx\"><cancelEventDefinition/></boundaryEvent>","handlingStrategy":"validation","validationCode":"// Validate at model/deploy time: cancel end events must sit inside a transaction with a cancel boundary\nboolean valid = hasTransactionSubprocessWithCancelBoundary(activityId);","typeGuard":null,"tryCatchPattern":"try { /* execute flow */ }\ncatch (ActivitiException e) { if (e.getMessage().contains(\"cancel boundary event\")) { flagModelingError(); } throw e; }","preventionTips":["Only use cancel end events inside transaction subprocesses","Always attach a cancel boundary event to the transaction","Validate BPMN models before deployment"],"tags":["bpmn","transaction","cancel-event","process-model"],"backgroundTag":"resource-not-found","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"}