{"record":{"id":"5f0d11e42c243dd1","repo":"flowable/flowable-engine","slug":"compensating-execution-not-set-for-eventsubscr","errorCode":null,"errorMessage":"Compensating execution not set for \" + eventSubscription","messagePattern":"Compensating execution not set for \" \\+ eventSubscription","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/event/CompensationEventHandler.java","lineNumber":53,"sourceCode":"import org.flowable.eventsubscription.service.impl.persistence.entity.CompensateEventSubscriptionEntity;\r\nimport org.flowable.eventsubscription.service.impl.persistence.entity.EventSubscriptionEntity;\r\n\r\n/**\r\n * @author Tijs Rademakers\r\n */\r\npublic class CompensationEventHandler implements EventHandler {\r\n\r\n    @Override\r\n    public String getEventHandlerType() {\r\n        return CompensateEventSubscriptionEntity.EVENT_TYPE;\r\n    }\r\n\r\n    @Override\r\n    public void handleEvent(EventSubscriptionEntity eventSubscription, Object payload, CommandContext commandContext) {\r\n\r\n        String configuration = eventSubscription.getConfiguration();\r\n        if (configuration == null) {\r\n            throw new FlowableException(\"Compensating execution not set for \" + eventSubscription);\r\n        }\r\n\r\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\r\n        ExecutionEntity compensatingExecution = processEngineConfiguration.getExecutionEntityManager().findById(configuration);\r\n\r\n        String processDefinitionId = compensatingExecution.getProcessDefinitionId();\r\n        Process process = ProcessDefinitionUtil.getProcess(processDefinitionId);\r\n        if (process == null) {\r\n            throw new FlowableException(\"Cannot start process instance. Process model (id = \" + processDefinitionId + \") could not be found for \" + eventSubscription);\r\n        }\r\n\r\n        FlowElement flowElement = process.getFlowElement(eventSubscription.getActivityId(), true);\r\n\r\n        if (flowElement instanceof SubProcess && !((SubProcess) flowElement).isForCompensation()) {\r\n\r\n            // descend into scope:\r\n            compensatingExecution.setScope(true);\r\n            List<CompensateEventSubscriptionEntity> eventsForThisScope = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService()\r","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/event/CompensationEventHandler.java#L35-L71","documentation":"Thrown by CompensationEventHandler.handleEvent when the compensation event subscription has a null configuration. The configuration stores the id of the compensating execution; without it the handler cannot locate the scope/execution that should run the compensation handler.","triggerScenarios":"Triggering compensation (e.g. transaction rollback / end of a transaction subprocess, or explicitly signaling the compensation event subscription) where eventSubscription.getConfiguration() returns null - i.e. an event subscription for a compensation boundary/handler created without its compensating-execution configuration.","commonSituations":"Manually inserted or migrated ACT_RU_EVENT_SUBSCR rows missing the CONFIG_ column value; engine bugs/upgrade scripts that lost the configuration; corrupt runtime data after failed transactions or inconsistent DB restores.","solutions":["Verify the ACT_RU_EVENT_SUBSCR row for the subscription has CONFIG_ set; if runtime data is corrupt, cancel the process instance and restart the flow.","Check that the process definition correctly models the compensation (boundary compensation events inside a transaction subprocess), then redeploy.","Restore consistent runtime data from backup or let the transaction roll back cleanly so the engine rebuilds subscriptions.","If reproducible, search/upgrade Flowable - known data-migration issues can drop the configuration value."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"EventSubscriptionEntity s = /* fetched */;\nif (s != null && s.getConfiguration() == null) {\n    throw new IllegalStateException(\"compensation subscription without configuration\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.signalEventReceived(compensationSignal);\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"Compensating execution not set\")) {\n        // runtime data corrupt: restart the process instance\n    }\n}","preventionTips":["Don't manipulate event-subscription rows directly in the database.","Model compensation with proper transaction subprocesses/boundary events.","Restore runtime data only from consistent, engine-created backups.","Test compensation paths in integration tests before production."],"tags":["bpmn","compensation","event-subscription","process-engine"],"backgroundTag":"missing-required-argument","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"}