{"record":{"id":"77d49ddcf9a8300f","repo":"flowable/flowable-engine","slug":"error-while-handling-compensation-event-eventsub","errorCode":null,"errorMessage":"Error while handling compensation event ${eventSubscription}","messagePattern":"Error while handling compensation event (.+?)","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/event/CompensationEventHandler.java","lineNumber":85,"sourceCode":"                if (commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {\r\n                    commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(\r\n                            ActivitiEventBuilder.createActivityEvent(FlowableEngineEventType.ACTIVITY_COMPENSATE,\r\n                                    compensationHandler.getId(),\r\n                                    (String) compensationHandler.getProperty(\"name\"),\r\n                                    compensatingExecution.getId(),\r\n                                    compensatingExecution.getProcessInstanceId(),\r\n                                    compensatingExecution.getProcessDefinitionId(),\r\n                                    (String) compensatingExecution.getActivity().getProperties().get(\"type\"),\r\n                                    compensatingExecution.getActivity().getActivityBehavior().getClass().getCanonicalName()),\r\n                            EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);\r\n                }\r\n                compensatingExecution.setActivity(compensationHandler);\r\n\r\n                // executing the atomic operation makes sure activity start events are fired\r\n                compensatingExecution.performOperation(AtomicOperation.ACTIVITY_START);\r\n\r\n            } catch (Exception e) {\r\n                throw new ActivitiException(\"Error while handling compensation event \" + eventSubscription, e);\r\n            }\r\n\r\n        }\r\n    }\r\n\r\n}\r\n","sourceCodeStart":67,"sourceCodeEnd":92,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/event/CompensationEventHandler.java#L67-L92","documentation":"Thrown by CompensationEventHandler.handleEvent when any exception occurs while executing a compensation handler for a compensation event subscription. The handler resolves the compensation handler activity, moves a compensating execution to it, and performs ACTIVITY_START; any failure inside that block (missing activity, process errors) is wrapped in this ActivitiException with the original exception as cause. Always inspect the cause to find the root problem.","triggerScenarios":"A compensation event is thrown (end/intermediate compensation event or process-level compensation) and handleEvent fails while creating/executing the compensating execution, e.g. the compensation handler activity cannot be resolved or throws during ACTIVITY_START.","commonSituations":"BPMN models with boundary compensation handlers whose target activity was changed or removed; engine data inconsistency where the event subscription references a stale activity; exceptions inside service tasks participating in compensation; upgrading flows where the process definition was redeployed with a different model while subscriptions persisted in the DB.","solutions":["Inspect the cause chain of the ActivitiException to find the real failure inside the compensation handler execution.","Verify the event subscription's activity id still exists in the deployed process definition; redeploy a consistent model and clear stale subscriptions.","Fix the underlying bug in the compensation handler code (service task/delegate) that threw during ACTIVITY_START.","Re-run the failed compensation from a clean process state after correcting the model; if needed delete the stale EventSubscription row."],"exampleFix":"// before: opaque wrap, root cause hidden\nthrow new ActivitiException(\"Error while handling compensation event \" + eventSubscription, e);\n// after: log cause explicitly and rethrow with context\ntry {\n    compensatingExecution.performOperation(AtomicOperation.ACTIVITY_START);\n} catch (Exception e) {\n    LOGGER.warn(\"Compensation handler {} failed\", compensationHandler != null ? compensationHandler.getId() : \"unknown\", e);\n    throw new ActivitiException(\"Error while handling compensation event \" + eventSubscription, e);\n}","handlingStrategy":"try-catch","validationCode":"// before signaling compensation, ensure the subscription and handler activity exist\nEventSubscription sub = runtimeService.createEventSubscriptionQuery()\n    .eventType(\"compensate\").singleResult();\nif (sub == null) throw new IllegalStateException(\"No compensation subscription\");","typeGuard":null,"tryCatchPattern":"try {\n    // trigger compensation path\n} catch (org.activiti.engine.ActivitiException e) {\n    LOGGER.error(\"Compensation failed: {}\", e.getMessage(), e.getCause());\n    throw new CompensationFailedException(e.getCause());\n}","preventionTips":["Always log the full cause chain; this error only wraps the real failure.","Keep compensation handler activity ids stable across process model versions.","Test compensation paths in CI with models that mimic production BPMN.","Avoid deleting deployments that still have live event subscriptions."],"tags":["bpmn","compensation","process-engine","workflow"],"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"}