flowable/flowable-engine · warning

compensation boundary catch must be connected to element wit

Error message

compensation boundary catch must be connected to element with isForCompensation=true

What it means

createAssociation() warns when an association connects a compensation boundary catch to an activity whose isForCompensation flag is not true. Compensation handlers must be marked isForCompensation="true"; otherwise the engine refuses to register it as the compensation handler and the association is ignored.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/handler/AbstractBpmnParseHandler.java:203

            // connected to a text annotation so skipping it
            return;
        }

        ActivityImpl sourceActivity = parentScope.findActivity(association.getSourceRef());
        ActivityImpl targetActivity = parentScope.findActivity(association.getTargetRef());

        // an association may reference elements that are not parsed as activities (like for instance
        // text annotations so do not throw an exception if sourceActivity or targetActivity are null)
        // However, we make sure they reference 'something':
        if (sourceActivity == null) {
            // bpmnModel.addProblem("Invalid reference sourceRef '" + association.getSourceRef() + "' of association element ", association.getId());
        } else if (targetActivity == null) {
            // bpmnModel.addProblem("Invalid reference targetRef '" + association.getTargetRef() + "' of association element ", association.getId());
        } else {
            if (sourceActivity.getProperty("type").equals("compensationBoundaryCatch")) {
                Object isForCompensation = targetActivity.getProperty(PROPERTYNAME_IS_FOR_COMPENSATION);
                if (isForCompensation == null || !(Boolean) isForCompensation) {
                    LOGGER.warn("compensation boundary catch must be connected to element with isForCompensation=true");
                } else {
                    ActivityImpl compensatedActivity = sourceActivity.getParentActivity();
                    compensatedActivity.setProperty(BpmnParse.PROPERTYNAME_COMPENSATION_HANDLER_ID, targetActivity.getId());
                }
            }
        }
    }

    protected Map<String, Object> processDataObjects(BpmnParse bpmnParse, Collection<ValuedDataObject> dataObjects, ScopeImpl scope) {
        Map<String, Object> variablesMap = new HashMap<>();
        // convert data objects to process variables
        if (dataObjects != null) {
            for (ValuedDataObject dataObject : dataObjects) {
                variablesMap.put(dataObject.getName(), dataObject.getValue());
            }
        }
        return variablesMap;
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Set isForCompensation="true" on the activity targeted by the compensation association
  2. Verify the association direction: source should be the compensation boundary catch, target the compensation handler
  3. Re-model the compensation pattern so the handler activity is a dedicated compensation task

Example fix

// before
<serviceTask id="undoTask"/>
<association sourceRef="compCatch" targetRef="undoTask"/>
// after
<serviceTask id="undoTask" isForCompensation="true"/>
<association sourceRef="compCatch" targetRef="undoTask"/>
Defensive patterns

Strategy: validation

Validate before calling

// Compensation targets must be marked isForCompensation
for (Association a : process.getArtifactsOfType(Association.class)) {
    BaseElement target = process.getFlowElement(a.getTargetRef());
    if (isCompensationBoundaryCatch(a.getSourceRef()) && !Boolean.TRUE.equals(isForCompensation(target)))
        throw new IllegalArgumentException("Compensation handler must set isForCompensation=true: " + a.getTargetRef());
}

Prevention

When it happens

Trigger: An association whose source is a compensation boundary catch (type "compensationBoundaryCatch") targets an activity lacking PROPERTYNAME_IS_FOR_COMPENSATION=true; logged in AbstractBpmnParseHandler.createAssociation() called from processArtifacts.

Common situations: Modeling a compensation handler without setting isForCompensation=true on the target task/subprocess; importing BPMN from other tools that omit the attribute.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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