{"record":{"id":"edf32214b98c978b","repo":"flowable/flowable-engine","slug":"no-sub-process-execution-found-for-cancel-end-even","errorCode":null,"errorMessage":"No sub process execution found for cancel end event in ${executionEntity}","messagePattern":"No sub process execution found for cancel end event in (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java","lineNumber":69,"sourceCode":"        ExecutionEntity currentlyExaminedExecution = executionEntityManager.findById(executionEntity.getParentId());\r\n        while (currentlyExaminedExecution != null && parentScopeExecution == null) {\r\n            if (currentlyExaminedExecution.getCurrentFlowElement() instanceof SubProcess subProcess) {\r\n                parentScopeExecution = currentlyExaminedExecution;\r\n                if (subProcess.getLoopCharacteristics() != null) {\r\n                    ExecutionEntity miExecution = parentScopeExecution.getParent();\r\n                    FlowElement miElement = miExecution.getCurrentFlowElement();\r\n                    if (miElement != null && miElement.getId().equals(subProcess.getId())) {\r\n                        parentScopeExecution = miExecution;\r\n                    }\r\n                }\r\n\r\n            } else {\r\n                currentlyExaminedExecution = executionEntityManager.findById(currentlyExaminedExecution.getParentId());\r\n            }\r\n        }\r\n\r\n        if (parentScopeExecution == null) {\r\n            throw new FlowableException(\"No sub process execution found for cancel end event in \" + executionEntity);\r\n        }\r\n\r\n        SubProcess subProcess = (SubProcess) parentScopeExecution.getCurrentFlowElement();\r\n        BoundaryEvent cancelBoundaryEvent = null;\r\n        if (CollectionUtil.isNotEmpty(subProcess.getBoundaryEvents())) {\r\n            for (BoundaryEvent boundaryEvent : subProcess.getBoundaryEvents()) {\r\n                if (CollectionUtil.isNotEmpty(boundaryEvent.getEventDefinitions()) &&\r\n                        boundaryEvent.getEventDefinitions().get(0) instanceof CancelEventDefinition) {\r\n\r\n                    cancelBoundaryEvent = boundaryEvent;\r\n                    break;\r\n                }\r\n            }\r\n        }\r\n\r\n        if (cancelBoundaryEvent == null) {\r\n            throw new FlowableException(\"Could not find cancel boundary event for cancel end event in \" + executionEntity);\r\n        }\r","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java#L51-L87","documentation":"Inside a transactional sub process, a cancel end event must execute within a scope whose execution tree leads to a sub-process (scope) parent execution. CancelEndEventActivityBehavior walks up the execution tree looking for that parent scope execution; if none is found, the cancel end event was not placed in a valid transactional sub process context and this FlowableException is thrown.","triggerScenarios":"A cancel end event is executed while the enclosing activity's parent chain contains no scope execution for a transactional sub process — e.g. the cancel end event is placed at process (root) level, or inside a plain embedded sub process that is not a transaction sub process.","commonSituations":"Modeler mistake: using a cancel end event outside a <transaction> element; refactoring a transaction sub process into an embedded sub process while keeping the cancel end event; copy-pasting cancel events into ordinary processes.","solutions":["Move the cancel end event inside a <transaction id=\"...\"> sub process element; cancel end events are only valid in transactional sub processes.","If no compensation/rollback semantics are needed, replace the cancel end event with a plain none end event.","Validate the BPMN model on deployment so the invalid placement is rejected before runtime.","Re-check the process after refactoring that cancel/boundary cancel pairs remain within the same transaction sub process."],"exampleFix":"// before: cancel end event in plain sub process\n<subProcess id=\"sp\"><endEvent id=\"end\"><cancelEventDefinition/></endEvent></subProcess>\n// after\n<transaction id=\"tx\"><endEvent id=\"end\"><cancelEventDefinition/></endEvent></transaction>","handlingStrategy":"validation","validationCode":"// static BPMN check before deployment\nelement.getElementsByTagNameNS(\"*\", \"cancelEventDefinition\"); // ensure cancel end events only exist inside <transaction> elements","typeGuard":null,"tryCatchPattern":"try { execution.signal(); }\ncatch (FlowableException e) { if (e.getMessage().startsWith(\"No sub process execution found\")) { refactorModelToTransactionSubProcess(); } else { throw e; } }","preventionTips":["Use cancel end events only inside <transaction> sub processes.","Validate BPMN with Flowable's validator in CI.","Review cancel usage after refactors from embedded to transaction sub processes.","Prefer plain end events unless rollback semantics are required."],"tags":["flowable","cancel-end-event","transaction-subprocess","bpmn"],"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-14T11:17:12.474Z"}