{"record":{"id":"b40369902ba4e5ff","repo":"Activiti/Activiti","slug":"exception-while-executing-event-listener","errorCode":null,"errorMessage":"Exception while executing event-listener","messagePattern":"Exception while executing event-listener","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-engine/src/main/java/org/activiti/engine/delegate/event/impl/ActivitiEventSupport.java","lineNumber":108,"sourceCode":"                dispatchEvent(event, listener);\n            }\n        }\n\n        // Call typed listeners, if any\n        List<ActivitiEventListener> typed = typedListeners.get(event.getType());\n        if (typed != null && !typed.isEmpty()) {\n            for (ActivitiEventListener listener : typed) {\n                dispatchEvent(event, listener);\n            }\n        }\n    }\n\n    protected void dispatchEvent(ActivitiEvent event, ActivitiEventListener listener) {\n        try {\n            listener.onEvent(event);\n        } catch (Throwable t) {\n            if (listener.isFailOnException()) {\n                throw new ActivitiException(\"Exception while executing event-listener\", t);\n            } else {\n                // Ignore the exception and continue notifying remaining listeners. The listener\n                // explicitly states that the exception should not bubble up\n                LOG.warn(\"Exception while executing event-listener, which was ignored\", t);\n            }\n        }\n    }\n\n    protected synchronized void addTypedEventListener(ActivitiEventListener listener, ActivitiEventType type) {\n        List<ActivitiEventListener> listeners = typedListeners.get(type);\n        if (listeners == null) {\n            // Add an empty list of listeners for this type\n            listeners = new CopyOnWriteArrayList<ActivitiEventListener>();\n            typedListeners.put(type, listeners);\n        }\n\n        if (!listeners.contains(listener)) {\n            listeners.add(listener);","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/Activiti/Activiti/blob/56435b1a97deeafdc09dd40074b056c89fba5a8a/activiti-core/activiti-engine/src/main/java/org/activiti/engine/delegate/event/impl/ActivitiEventSupport.java#L90-L126","documentation":"When notifying a single listener, the wrapped ActivitiException('Exception while executing event-listener') is thrown only if that listener's isFailOnException() returns true. The original listener exception is attached as cause. Listeners that return false from isFailOnException() get their exceptions logged and swallowed instead. This wraps arbitrary listener bugs into an ActivitiException propagated out of dispatchEvent.","triggerScenarios":"A registered ActivitiEventListener's onEvent(event) throws any Throwable AND the listener overrides isFailOnException() to return true (the default for many engine listeners), causing the wrapped exception to bubble up to the dispatchEvent caller.","commonSituations":"Business logic in a listener throwing (e.g. NPE on missing process variables, DB errors in a listener that writes audit records); adding a fail-fast listener for events fired inside a transaction, which then rolls back the transaction.","solutions":["Read the getCause() of the ActivitiException to find the actual listener bug and fix that code.","If failures in this listener should not break the process, override isFailOnException() to return false so exceptions are only logged.","Wrap your listener's onEvent body in its own try-catch to control the failure policy per-exception.","Move heavy/fallible work out of the listener into an async job if it should not affect the transaction."],"exampleFix":"// before\nclass AuditListener implements ActivitiEventListener {\n    public void onEvent(ActivitiEvent e) { writeAudit(e); } // may throw\n    public boolean isFailOnException() { return true; }\n}\n// after\nclass AuditListener implements ActivitiEventListener {\n    public void onEvent(ActivitiEvent e) {\n        try { writeAudit(e); } catch (Exception ex) { LOG.error(\"audit failed\", ex); }\n    }\n    public boolean isFailOnException() { return false; }\n}","handlingStrategy":"try-catch","validationCode":"// Review listener implementations before registration:\n// ensure onEvent is defensive (null-checks, DB error handling)\n// and isFailOnException() reflects the intended failure policy.","typeGuard":"null","tryCatchPattern":"try {\n    runtimeService.dispatchEvent(event);\n} catch (ActivitiException e) {\n    LOG.error(\"Event listener failed\", e.getCause());\n}","preventionTips":["Read the cause chain to find the real listener exception","Return false from isFailOnException() for best-effort listeners","Wrap fallible listener logic in its own try-catch","Keep listeners lightweight; offload heavy work to async jobs"],"tags":["java","activiti","event-listener","wrapped-exception"],"backgroundTag":"api-error-response","analyzedSha":"56435b1a97deeafdc09dd40074b056c89fba5a8a","analyzedAt":"2026-09-09T21:00:06.703Z","contentChangedAt":"2026-09-09T21:00:06.703Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}