{"record":{"id":"c3025c7662e5e136","repo":"flowable/flowable-engine","slug":"error-while-handling-compensation-event-events","errorCode":null,"errorMessage":"Error while handling compensation event \" + eventSubscription","messagePattern":"Error while handling compensation event \" \\+ eventSubscription","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/event/CompensationEventHandler.java","lineNumber":114,"sourceCode":"                                    if (targetActivity.isForCompensation()) {\r\n                                        compensationActivity = targetActivity;\r\n                                        break;\r\n                                    }\r\n                                }\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                \r\n                if (compensationActivity != null) {\r\n                    flowElement = compensationActivity;\r\n                }\r\n                \r\n                compensatingExecution.setCurrentFlowElement(flowElement);\r\n                CommandContextUtil.getAgenda().planContinueProcessInCompensation(compensatingExecution);\r\n\r\n            } catch (Exception e) {\r\n                throw new FlowableException(\"Error while handling compensation event \" + eventSubscription, e);\r\n            }\r\n\r\n        }\r\n    }\r\n\r\n}\r\n","sourceCodeStart":96,"sourceCodeEnd":121,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/event/CompensationEventHandler.java#L96-L121","documentation":"Flowable's CompensationEventHandler processes compensation events (used by transactional subprocesses and compensation boundary events). This error wraps any unexpected exception thrown while executing a compensation, preserving the original exception as the cause. It indicates the compensation logic failed mid-flight, e.g. while resolving the flow element or planning the compensation continuation.","triggerScenarios":"Calling runtimeService.signalEventReceived / triggering a compensation event subscription where the compensating execution's current flow element lookup or planContinueProcessInCompensation throws (missing BPMN element, corrupted execution state, exception in an underlying command).","commonSituations":"BPMN model changed after process instances were deployed (stale process definition cache), execution pointing to a removed compensation boundary event, database inconsistency after a failed migration, bugs in custom FlowableCommandContext listeners.","solutions":["Read the chained cause (e.getCause()) of the FlowableException; it contains the real failure.","Verify the deployed BPMN XML still contains the compensation boundary event / event subprocess referenced by the event subscription.","Clear the process definition cache or redeploy the process definition if the model was changed after instances were started.","Check ACT_RU_EXECUTION / ACT_RU_EVENT_SUBSCR rows for consistency; remove orphaned subscriptions if the process instance is already ended.","Upgrade Flowable or open an issue with the cause stack trace if the state is valid — this is often an engine bug."],"exampleFix":"// before\n} catch (Exception e) {\n    // swallowing details, only top message visible\n}\n// after\ntry {\n    // handle compensation event\n} catch (FlowableException e) {\n    LOGGER.error(\"Compensation failed for subscription {}: {}\", eventSubscription.getId(), e.getCause(), e);\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"EventSubscription sub = runtimeService.createEventSubscriptionQuery().subscriptionId(id).singleResult();\nif (sub == null || sub.getExecutionId() == null) throw new IllegalStateException(\"No valid compensation subscription: \" + id);","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.signalEventReceived(compensationSignal, subscriptionId);\n} catch (FlowableException e) {\n    LOGGER.error(\"Compensation handling failed for {}: cause={}\", subscriptionId, e.getCause(), e);\n    throw new CompensationFailedException(subscriptionId, e.getCause());\n}","preventionTips":["Always log the chained cause; the wrapper message alone is not diagnostic.","Keep BPMN element ids stable across redeploys of processes with active instances.","Test compensation paths (transactional subprocesses, compensation handlers) in CI.","Monitor ACT_RU_EVENT_SUBSCR for orphaned compensation subscriptions after migrations."],"tags":["flowable","bpmn","compensation","event-handling"],"backgroundTag":"internal-invariant-violation","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"}