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

  1. Add isForCompensation="true" to the activity referenced by the association's targetRef, then redeploy.
  2. Confirm the association's targetRef matches an existing activity id in the process.
  3. Use a serviceTask/task element designed for compensation and ensure it is only reachable via compensation (no incoming sequence flows).
  4. 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

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


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