flowable/flowable-engine · error · FlowableException

Could not find cancel boundary event for cancel end event in

Error message

Could not find cancel boundary event for cancel end event in ${executionEntity}

What it means

After locating the parent scope execution for a cancel end event, CancelEndEventActivityBehavior searches that scope's flow element (the SubProcess) for a boundary event with a cancelEventDefinition. If the transaction sub process has no cancel boundary event attached, the cancel has nothing to target, so this FlowableException is thrown.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/CancelEndEventActivityBehavior.java:86

        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);
        }

        ExecutionEntity newParentScopeExecution = null;
        currentlyExaminedExecution = executionEntityManager.findById(parentScopeExecution.getParentId());
        while (currentlyExaminedExecution != null && newParentScopeExecution == null) {
            if (currentlyExaminedExecution.isScope()) {
                newParentScopeExecution = currentlyExaminedExecution;
            } else {
                currentlyExaminedExecution = executionEntityManager.findById(currentlyExaminedExecution.getParentId());
            }
        }

        if (newParentScopeExecution == null) {
            throw new FlowableException("Programmatic error: no parent scope execution found for boundary event " + cancelBoundaryEvent.getId() + " for " + parentScopeExecution);
        }

        ScopeUtil.createCopyOfSubProcessExecutionForCompensation(parentScopeExecution);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Attach a cancel boundary event to the transaction sub process: <boundaryEvent id="cancelBoundary" attachedToRef="tx"><cancelEventDefinition/></boundaryEvent>.
  2. If no cancellation handling is required, remove the cancel end event and use a normal end event instead.
  3. Ensure the boundary event's attachedToRef points at the transaction sub process id, not an inner activity.
  4. Validate the model at deployment time to catch cancel end/boundary mismatches early.

Example fix

// before: transaction sub process without cancel boundary event
<transaction id="tx">...</transaction>
// after
<boundaryEvent id="cancelB" attachedToRef="tx"><cancelEventDefinition/></boundaryEvent>
Defensive patterns

Strategy: validation

Validate before calling

// assert every transaction sub process with a cancel end event has a matching boundary cancel
for (Element tx : txSubProcesses) {
  boolean hasCancelEnd = hasChild(tx, "cancelEventDefinition");
  boolean hasCancelBoundary = hasBoundaryCancelAttachedTo(tx.getAttribute("id"));
  if (hasCancelEnd && !hasCancelBoundary) throw new IllegalStateException("tx " + tx.getAttribute("id") + " missing cancel boundary event");
}

Try / catch

try { execution.signal(); }
catch (FlowableException e) { if (e.getMessage().startsWith("Could not find cancel boundary event")) { addCancelBoundaryAndRedeploy(); } else { throw e; } }

Prevention

When it happens

Trigger: A cancel end event fires inside a transaction sub process that has no boundary event of type <cancelEventDefinition/> attached — the sub process contains the cancel end event but no matching cancel boundary catch.

Common situations: Modeler added a cancel end event (to force rollback) but forgot to attach the cancel boundary event; the boundary event was deleted during refactoring; the boundary event is attached to a different element than the transaction sub process.

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/4094c19e09e7c620. Report an issue: GitHub.