flowable/flowable-engine · error · ActivitiIllegalArgumentException
Cannot throw process-instance scoped message, since the…
Error message
Cannot throw process-instance scoped message, since the dispatched event is not part of an ongoing process instance
What it means
Thrown as ActivitiIllegalArgumentException when a MessageThrowingEventListener tries to throw a process-instance-scoped message but the dispatched FlowableEngineEvent has a null processInstanceId. The engine cannot resolve a process instance scope to look up the message event subscription, so the throw is rejected up front.
Solutions
- Register the message-throwing listener only for events that occur within a process instance execution (e.g. ACTIVITY_COMPLETED, TASK_COMPLETED), not engine-level events.
- Check the FlowableEngineEvent.getProcessInstanceId() in your own listener logic before delegating to the message-throwing listener.
- If the message should be global rather than per-instance, use a non-process-instance-scoped message mechanism instead.
- Review the process definition extension elements and remove the listener from events that fire outside a process instance.
Example fix
// before: listener bound to a global event <activiti:eventListener events="ENGINE_CREATED" eventType="message-throwing" messageName="myMessage"/> // after: bind to an in-execution event <activiti:eventListener events="ACTIVITY_COMPLETED" eventType="message-throwing" messageName="myMessage"/>
Defensive patterns
Strategy: validation
Validate before calling
if (event instanceof FlowableEngineEvent) {
if (((FlowableEngineEvent) event).getProcessInstanceId() == null) {
throw new IllegalStateException("Message-throwing listener requires an event inside a process instance");
}
} Type guard
boolean isExecutionScoped(FlowableEvent event) {
return event instanceof FlowableEngineEvent
&& ((FlowableEngineEvent) event).getProcessInstanceId() != null;
} Try / catch
try {
dispatchEvent(event);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("not part of an ongoing process instance")) {
logger.warn("Skipped message throw: event not execution-scoped");
} else { throw e; }
} Prevention
- Bind message-throwing event listeners only to in-execution events (ACTIVITY_*, TASK_*).
- Never attach instance-scoped listeners to engine-level events (ENGINE_CREATED, ENGINE_CLOSED).
- Review process definition eventListener extension elements during code review.
When it happens
Trigger: onEvent is invoked with an engine event whose getProcessInstanceId() returns null — e.g. a process-engine-level event (deployment, engine start/stop) registered for a message-throwing listener, while the listener's message is scoped to a process instance.
Common situations: Registering a message-throwing event listener on global/engine-level events in the process engine configuration; events dispatched during deployment or engine bootstrap that have no process instance attached; misconfigured <activiti:eventListener> entries in the process definition.
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
- Cannot throw process-instance scoped signal, since the…
- Cannot create 'script' task listener. Missing ScriptInfo.
- Cannot deploy process definition
- Cannot deploy process definition
- Cannot start process instance by message: subscription to…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/44032c930d05653d.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/MessageThrowingEventListener.java:44
/**
* An {@link FlowableEventListener} that throws a message event when an event is dispatched to it. Sends the message to the execution the event was fired from. If the execution is not subscribed to a
* message, the process-instance is checked.
*
* @author Frederik Heremans
*
*/
public class MessageThrowingEventListener extends BaseDelegateEventListener {
protected String messageName;
protected Class<?> entityClass;
@Override
public void onEvent(FlowableEvent event) {
if (isValidEvent(event) && event instanceof FlowableEngineEvent) {
FlowableEngineEvent engineEvent = (FlowableEngineEvent) event;
if (engineEvent.getProcessInstanceId() == null) {
throw new ActivitiIllegalArgumentException(
"Cannot throw process-instance scoped message, since the dispatched event is not part of an ongoing process instance");
}
CommandContext commandContext = Context.getCommandContext();
List<EventSubscriptionEntity> subscriptionEntities = commandContext.getEventSubscriptionEntityManager()
.findEventSubscriptionsByNameAndExecution(MessageEventHandler.EVENT_HANDLER_TYPE, messageName, engineEvent.getExecutionId());
// Revert to messaging the process instance
if (subscriptionEntities.isEmpty() && engineEvent.getProcessInstanceId() != null &&
!engineEvent.getExecutionId().equals(engineEvent.getProcessInstanceId())) {
subscriptionEntities = commandContext.getEventSubscriptionEntityManager()
.findEventSubscriptionsByNameAndExecution(MessageEventHandler.EVENT_HANDLER_TYPE, messageName, engineEvent.getProcessInstanceId());
}
for (EventSubscriptionEntity signalEventSubscriptionEntity : subscriptionEntities) {
signalEventSubscriptionEntity.eventReceived(null, false);
}View on GitHub (pinned to d6d39ce1c6)