flowable/flowable-engine · warning
Exception occurred while dispatching job failure event…
Error message
Exception occurred while dispatching job failure event, ignoring.
What it means
WARN log from DefaultAsyncRunnableExecutionExceptionHandler: after a job fails execution, Flowable tries to dispatch a JOB_EXECUTION_FAILURE event to the event dispatcher; if that dispatch itself throws, it is logged and swallowed so the original job-failure handling is not disrupted. Your job failed AND the failure-event listeners blew up.
Solutions
- Inspect the chained 'ignore' exception to find which event listener threw
- Fix or wrap the failing listener so it handles its own errors
- Temporarily remove the listener to confirm it is the culprit
- If listeners must do I/O, add their own retry/circuit-breaker inside the listener
Example fix
// before
public void onEvent(FlowableEvent event) { notifyMonitoringRemote(event); } // throws on network error
// after
public void onEvent(FlowableEvent event) {
try { notifyMonitoringRemote(event); } catch (Exception e) { LOG.warn("monitoring notify failed", e); }
} Defensive patterns
Strategy: try-catch
Validate before calling
// validate listeners at startup
engineConfig.getEventListeners().forEach(l -> {
if (!(l instanceof FlowableEventListener)) throw new IllegalStateException("bad listener registration");
}); Try / catch
try {
eventDispatcher.dispatchEvent(failureEvent, engineName);
} catch (Throwable ignore) {
LOGGER.warn("Exception occurred while dispatching job failure event, ignoring.", ignore);
} Prevention
- Make every custom event listener swallow-and-log its own exceptions
- Avoid blocking I/O inside event listeners
- Test listeners against JOB_EXECUTION_FAILURE events
When it happens
Trigger: A registered event listener for JOB_EXECUTION_FAILURE throws during handleEvent; event dispatcher enabled but a listener misbehaves (NPE, remote call failure, transaction issues).
Common situations: Custom event listeners doing I/O (HTTP, messaging) that fail; listeners assuming transactional context that isn't present; third-party integrations (Camunda-style audit listeners) incompatible with the event payload.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Cannot create 'script' task listener. Missing ScriptInfo.
- Cannot delete
- Custom properties resolver delegate expression " +…
- doesn't implement CustomPropertiesResolver
- doesn't implement TransactionDependentExecutionListener
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/af7ad035a7a8e100.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/asyncexecutor/DefaultAsyncRunnableExecutionExceptionHandler.java:69
}
}
CommandConfig commandConfig = jobServiceConfiguration.getCommandExecutor().getDefaultConfig().transactionRequiresNew();
FailedJobCommandFactory failedJobCommandFactory = jobServiceConfiguration.getFailedJobCommandFactory();
Command<Object> cmd = failedJobCommandFactory.getCommand(job.getId(), exception);
LOGGER.trace("Using FailedJobCommandFactory '{}' and command of type '{}'", failedJobCommandFactory.getClass(), cmd.getClass());
jobServiceConfiguration.getCommandExecutor().execute(commandConfig, cmd);
// Dispatch an event, indicating job execution failed in a
// try-catch block, to prevent the original exception to be swallowed
FlowableEventDispatcher eventDispatcher = jobServiceConfiguration.getEventDispatcher();
if (eventDispatcher != null && eventDispatcher.isEnabled()) {
try {
eventDispatcher.dispatchEvent(FlowableJobEventBuilder.createEntityExceptionEvent(
FlowableEngineEventType.JOB_EXECUTION_FAILURE, job, exception), jobServiceConfiguration.getEngineName());
} catch (Throwable ignore) {
LOGGER.warn("Exception occurred while dispatching job failure event, ignoring.", ignore);
}
}
return null;
}
});
return true;
}
}
View on GitHub (pinned to d6d39ce1c6)