{"record":{"id":"5e6657652f487a6d","repo":"flowable/flowable-engine","slug":"parent-activity-for-boundary-compensation-event-co","errorCode":null,"errorMessage":"Parent activity for boundary compensation event could not be found for ${executionEntity}","messagePattern":"Parent activity for boundary compensation event could not be found for (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/BoundaryCompensateEventActivityBehavior.java","lineNumber":74,"sourceCode":"            throw new FlowableException(\"Process model for \" + executionEntity + \" could not be found\");\n        }\n\n        Activity sourceActivity = null;\n        Activity compensationActivity = null;\n        List<Association> associations = process.findAssociationsWithSourceRefRecursive(boundaryEvent.getId());\n        for (Association association : associations) {\n            sourceActivity = boundaryEvent.getAttachedToRef();\n            FlowElement targetElement = process.getFlowElement(association.getTargetRef(), true);\n            if (targetElement instanceof Activity activity) {\n                if (activity.isForCompensation()) {\n                    compensationActivity = activity;\n                    break;\n                }\n            }\n        }\n        \n        if (sourceActivity == null) {\n            throw new FlowableException(\"Parent activity for boundary compensation event could not be found for \" + executionEntity);\n        }\n\n        if (compensationActivity == null) {\n            throw new FlowableException(\"Compensation activity could not be found (or it is missing 'isForCompensation=\\\"true\\\"') for \" + executionEntity);\n        }\n\n        // find SubProcess or Process instance execution\n        ExecutionEntity scopeExecution = null;\n        ExecutionEntity parentExecution = executionEntity.getParent();\n        while (scopeExecution == null && parentExecution != null) {\n            if (parentExecution.getCurrentFlowElement() instanceof SubProcess) {\n                scopeExecution = parentExecution;\n\n            } else if (parentExecution.isProcessInstanceType()) {\n                scopeExecution = parentExecution;\n            } else {\n                parentExecution = parentExecution.getParent();\n            }","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/BoundaryCompensateEventActivityBehavior.java#L56-L92","documentation":"Flowable throws this when the BPMN model contains a compensation boundary event but no source activity attached to it can be found. execute() scans the process associations (findAssociationsWithSourceRefRecursive) for an association originating from the boundary event and identifies the parent activity; if sourceActivity stays null, the model is malformed — the boundary event has no association link to the activity it compensates.","triggerScenarios":"Deploying/running a BPMN XML where a boundaryEvent with a compensateEventDefinition has no <bpmn:association> (associationDirection/association element in the BPMNDiagram/definitions) linking it to a source activity, or the association's sourceRef points to a non-existent activity id.","commonSituations":"Hand-edited BPMN XML missing the association element; modelers that don't render compensation associations; renaming an activity id without updating the association sourceRef; copying a boundary event from another diagram without its association.","solutions":["Open the BPMN XML and add an <bpmn:association> whose sourceRef is the activity being compensated and targetRef is the boundary event (or check it isn't pointing at a wrong/renamed id).","Redeploy the process definition after fixing the XML.","Validate the model with a BPMN validator or the Flowable modeler before deploying.","If the association exists, confirm the sourceRef id matches the actual activity id in the same process/subProcess scope."],"exampleFix":"// before (boundary event with no association)\n<bpmn:boundaryEvent id=\"compBoundary\" attachedToRef=\"task1\">\n  <bpmn:compensateEventDefinition/>\n</bpmn:boundaryEvent>\n\n// after (association added)\n<bpmn:boundaryEvent id=\"compBoundary\" attachedToRef=\"task1\">\n  <bpmn:compensateEventDefinition/>\n</bpmn:boundaryEvent>\n<bpmn:association id=\"assoc1\" sourceRef=\"task1\" targetRef=\"compBoundary\"/>","handlingStrategy":"validation","validationCode":"boolean hasCompensationAssociation(BpmnModel model, String boundaryEventId) {\n    Process process = model.getMainProcess();\n    return !process.findAssociationsWithSourceRefRecursive(boundaryEventId).isEmpty();\n}","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.startProcessInstanceByKey(\"myProcess\");\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"Parent activity for boundary compensation event\")) {\n        // model defect: fix association in BPMN XML and redeploy\n    }\n}","preventionTips":["Always model compensation associations via the Flowable modeler, not raw XML edits.","Run BPMN model validation as part of the CI deployment pipeline.","After renaming activity ids, search the XML for stale association sourceRef/targetRef values."],"tags":["flowable","bpmn","compensation","model-validation","association"],"backgroundTag":"schema-validation-failed","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}