flowable/flowable-engine · error · FlowableException
No sub process execution found for cancel end event in ${exe
Error message
No sub process execution found for cancel end event in ${executionEntity} What it means
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.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java:69
ExecutionEntity currentlyExaminedExecution = executionEntityManager.findById(executionEntity.getParentId());
while (currentlyExaminedExecution != null && parentScopeExecution == null) {
if (currentlyExaminedExecution.getCurrentFlowElement() instanceof SubProcess subProcess) {
parentScopeExecution = currentlyExaminedExecution;
if (subProcess.getLoopCharacteristics() != null) {
ExecutionEntity miExecution = parentScopeExecution.getParent();
FlowElement miElement = miExecution.getCurrentFlowElement();
if (miElement != null && miElement.getId().equals(subProcess.getId())) {
parentScopeExecution = miExecution;
}
}
} else {
currentlyExaminedExecution = executionEntityManager.findById(currentlyExaminedExecution.getParentId());
}
}
if (parentScopeExecution == null) {
throw new FlowableException("No sub process execution found for cancel end event in " + executionEntity);
}
SubProcess subProcess = (SubProcess) parentScopeExecution.getCurrentFlowElement();
BoundaryEvent cancelBoundaryEvent = null;
if (CollectionUtil.isNotEmpty(subProcess.getBoundaryEvents())) {
for (BoundaryEvent boundaryEvent : subProcess.getBoundaryEvents()) {
if (CollectionUtil.isNotEmpty(boundaryEvent.getEventDefinitions()) &&
boundaryEvent.getEventDefinitions().get(0) instanceof CancelEventDefinition) {
cancelBoundaryEvent = boundaryEvent;
break;
}
}
}
if (cancelBoundaryEvent == null) {
throw new FlowableException("Could not find cancel boundary event for cancel end event in " + executionEntity);
}
View on GitHub (pinned to d6d39ce1c6)
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.
Example fix
// before: cancel end event in plain sub process <subProcess id="sp"><endEvent id="end"><cancelEventDefinition/></endEvent></subProcess> // after <transaction id="tx"><endEvent id="end"><cancelEventDefinition/></endEvent></transaction>
Defensive patterns
Strategy: validation
Validate before calling
// static BPMN check before deployment
element.getElementsByTagNameNS("*", "cancelEventDefinition"); // ensure cancel end events only exist inside <transaction> elements Try / catch
try { execution.signal(); }
catch (FlowableException e) { if (e.getMessage().startsWith("No sub process execution found")) { refactorModelToTransactionSubProcess(); } else { throw e; } } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Could not find cancel boundary event for cancel end event in
- BPMN XSD could not be found
- The bpmn 2.0 xml is not properly encoded
- The ${task} cannot be deleted because is part of a running p
- ${sequenceFlowId} does not match a sequence flow for ${deleg
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/edf32214b98c978b.
Report an issue: GitHub.