flowable/flowable-engine · error · ActivitiException
No execution context active and event is not related to an…
Error message
No execution context active and event is not related to an execution. No compensation event can be thrown.
What it means
ErrorThrowingEventListener (for compensation/error events) needs an execution to propagate the error through. If there is no active command context execution and the dispatched event carries no executionId, propagation is impossible and it throws ActivitiException.
Solutions
- Attach the error-throwing listener only to execution-scoped event types that carry an executionId
- Dispatch the listener within a command context (e.g. from process logic rather than external threads)
- Check event types in the listener registration and remove ones unrelated to executions
- If the event legitimately has no execution, use a different listener mechanism that doesn't need an execution
Example fix
// before
<flowable:eventListener events="ENGINE_CREATED" delegateExpression="${errorThrowingListener}"/>
// after
<flowable:eventListener events="ACTIVITY_COMPLETED" delegateExpression="${errorThrowingListener}"/> Defensive patterns
Strategy: validation
Validate before calling
// only register error-throwing listeners for execution-bound events
java.util.Set<String> EXECUTION_EVENTS = java.util.Set.of("ACTIVITY_STARTED","ACTIVITY_COMPLETED","ACTIVITY_SIGNALED","PROCESS_STARTED","PROCESS_COMPLETED");
if (!EXECUTION_EVENTS.contains(eventType)) throw new IllegalArgumentException("error-throwing listener needs execution-bound event, got " + eventType); Try / catch
try {
runtimeService.startProcessInstanceByKey("myProcess");
} catch (org.activiti.engine.ActivitiException e) {
if (e.getMessage() != null && e.getMessage().contains("No execution context active")) {
logger.error("Error-throwing listener fired without execution context", e);
}
throw e;
} Prevention
- Register error-throwing listeners only on execution-related event types
- Do not dispatch such listeners from threads without a command context
- Review engine-wide (global) listener registrations for execution dependence
When it happens
Trigger: A global engine event listener configured to throw an error event fires for an event unrelated to any execution (e.g. engine-level event) or outside an active command context, so neither Context.getExecutionEntityManager lookup nor engineEvent.getExecutionId() yields an execution.
Common situations: Registering an error-throwing listener on engine-wide events (e.g. CONFIGURATION_*, job/async events without execution); dispatching events from a non-command thread; listener used on events that occur before/after process execution exists.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Class does not implement
- Delegate expression did not resolve to an implementation of…
- BPMN XSD could not be found
- Cannot create 'script' task listener. Missing ScriptInfo.
- Cannot have more than one message event subscription with…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/9fce442a5c426b10.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ErrorThrowingEventListener.java:46
public class ErrorThrowingEventListener extends BaseDelegateEventListener {
protected String errorCode;
@Override
public void onEvent(FlowableEvent event) {
if (isValidEvent(event) && event instanceof FlowableEngineEvent) {
FlowableEngineEvent engineEvent = (FlowableEngineEvent) event;
ExecutionEntity execution = null;
if (Context.isExecutionContextActive()) {
execution = Context.getExecutionContext().getExecution();
} else if (engineEvent.getExecutionId() != null) {
// Get the execution based on the event's execution ID instead
execution = Context.getCommandContext().getExecutionEntityManager().findExecutionById(engineEvent.getExecutionId());
}
if (execution == null) {
throw new ActivitiException("No execution context active and event is not related to an execution. No compensation event can be thrown.");
}
try {
ErrorPropagation.propagateError(errorCode, execution);
} catch (Exception e) {
throw new ActivitiException("Error while propagating error-event", e);
}
}
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
@Override
public boolean isFailOnException() {
return true;
}View on GitHub (pinned to d6d39ce1c6)