flowable/flowable-engine · error · FlowableException
Compensation activity could not be found (or it is missing '
Error message
Compensation activity could not be found (or it is missing 'isForCompensation="true"') for ${executionEntity} What it means
Flowable throws this when the compensation boundary event's association points to an activity, but no target activity marked isForCompensation="true" can be found. execute() walks the associations to find compensationActivity; it stays null when the association target is missing or the compensation handler lacks the isForCompensation attribute, which Flowable requires to treat it as a compensation handler.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/BoundaryCompensateEventActivityBehavior.java:78
Activity compensationActivity = null;
List<Association> associations = process.findAssociationsWithSourceRefRecursive(boundaryEvent.getId());
for (Association association : associations) {
sourceActivity = boundaryEvent.getAttachedToRef();
FlowElement targetElement = process.getFlowElement(association.getTargetRef(), true);
if (targetElement instanceof Activity activity) {
if (activity.isForCompensation()) {
compensationActivity = activity;
break;
}
}
}
if (sourceActivity == null) {
throw new FlowableException("Parent activity for boundary compensation event could not be found for " + executionEntity);
}
if (compensationActivity == null) {
throw new FlowableException("Compensation activity could not be found (or it is missing 'isForCompensation=\"true\"') for " + executionEntity);
}
// find SubProcess or Process instance execution
ExecutionEntity scopeExecution = null;
ExecutionEntity parentExecution = executionEntity.getParent();
while (scopeExecution == null && parentExecution != null) {
if (parentExecution.getCurrentFlowElement() instanceof SubProcess) {
scopeExecution = parentExecution;
} else if (parentExecution.isProcessInstanceType()) {
scopeExecution = parentExecution;
} else {
parentExecution = parentExecution.getParent();
}
}
if (scopeExecution == null) {
throw new FlowableException("Could not find a scope execution for compensation boundary event " + boundaryEvent.getId() + " for " + executionEntity);View on GitHub (pinned to d6d39ce1c6)
Solutions
- Add isForCompensation="true" to the activity referenced by the association's targetRef, then redeploy.
- Confirm the association's targetRef matches an existing activity id in the process.
- Use a serviceTask/task element designed for compensation and ensure it is only reachable via compensation (no incoming sequence flows).
- Re-export the diagram from the Flowable modeler to regenerate correct association/attributes.
Example fix
// before <bpmn:serviceTask id="undoTask" flowable:class="com.acme.UndoDelegate"/> // after <bpmn:serviceTask id="undoTask" isForCompensation="true" flowable:class="com.acme.UndoDelegate"/>
Defensive patterns
Strategy: validation
Validate before calling
boolean hasMarkedCompensationHandler(BpmnModel model, String boundaryEventId) {
Process process = model.getMainProcess();
return process.findAssociationsWithSourceRefRecursive(boundaryEventId).stream()
.map(a -> model.getFlowElement(a.getTargetRef()))
.filter(Objects::nonNull)
.anyMatch(fe -> fe instanceof Activity && Boolean.TRUE.equals(((Activity) fe).isForCompensation()));
} Try / catch
try {
runtimeService.startProcessInstanceByKey("myProcess");
} catch (FlowableException e) {
if (e.getMessage().contains("isForCompensation")) {
// handler not marked: add isForCompensation="true" and redeploy
}
} Prevention
- Always set isForCompensation="true" on activities used as compensation handlers.
- Keep compensation handlers without incoming sequence flows so they are only invoked by compensation.
- Validate the deployed BpmnModel programmatically in integration tests before go-live.
When it happens
Trigger: A boundary compensate event has an association whose targetRef activity is not flagged isForCompensation="true", the targetRef id does not exist in the model, or the association points at a plain task/service task instead of a compensation handler.
Common situations: Forgetting isForCompensation="true" on the compensation task in hand-written XML; the modeler generating a compensation event but the handler not being marked; typos in the handler's activity id; modeling compensation without a proper compensation handler activity.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Parent activity for boundary compensation event could not be
- Process model for ${executionEntity} could not be found
- Process model (id = ${processDefinitionId}) could not be fou
- Error while handling compensation event " + eventSubscriptio
- BPMN XSD could not be found
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/c712c37098f78a34.
Report an issue: GitHub.