{"record":{"id":"44032c930d05653d","repo":"flowable/flowable-engine","slug":"cannot-throw-process-instance-scoped-message-sinc-44032c","errorCode":null,"errorMessage":"Cannot throw process-instance scoped message, since the dispatched event is not part of an ongoing process instance","messagePattern":"Cannot throw process-instance scoped message, since the dispatched event is not part of an ongoing process instance","errorType":"exception","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/MessageThrowingEventListener.java","lineNumber":44,"sourceCode":"/**\n * 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\n * message, the process-instance is checked.\n * \n * @author Frederik Heremans\n * \n */\npublic class MessageThrowingEventListener extends BaseDelegateEventListener {\n\n    protected String messageName;\n    protected Class<?> entityClass;\n\n    @Override\n    public void onEvent(FlowableEvent event) {\n        if (isValidEvent(event) && event instanceof FlowableEngineEvent) {\n            FlowableEngineEvent engineEvent = (FlowableEngineEvent) event;\n\n            if (engineEvent.getProcessInstanceId() == null) {\n                throw new ActivitiIllegalArgumentException(\n                        \"Cannot throw process-instance scoped message, since the dispatched event is not part of an ongoing process instance\");\n            }\n\n            CommandContext commandContext = Context.getCommandContext();\n            List<EventSubscriptionEntity> subscriptionEntities = commandContext.getEventSubscriptionEntityManager()\n                    .findEventSubscriptionsByNameAndExecution(MessageEventHandler.EVENT_HANDLER_TYPE, messageName, engineEvent.getExecutionId());\n\n            // Revert to messaging the process instance\n            if (subscriptionEntities.isEmpty() && engineEvent.getProcessInstanceId() != null &&\n                    !engineEvent.getExecutionId().equals(engineEvent.getProcessInstanceId())) {\n\n                subscriptionEntities = commandContext.getEventSubscriptionEntityManager()\n                        .findEventSubscriptionsByNameAndExecution(MessageEventHandler.EVENT_HANDLER_TYPE, messageName, engineEvent.getProcessInstanceId());\n            }\n\n            for (EventSubscriptionEntity signalEventSubscriptionEntity : subscriptionEntities) {\n                signalEventSubscriptionEntity.eventReceived(null, false);\n            }","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/MessageThrowingEventListener.java#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: listener bound to a global event\n<activiti:eventListener events=\"ENGINE_CREATED\" eventType=\"message-throwing\" messageName=\"myMessage\"/>\n\n// after: bind to an in-execution event\n<activiti:eventListener events=\"ACTIVITY_COMPLETED\" eventType=\"message-throwing\" messageName=\"myMessage\"/>","handlingStrategy":"validation","validationCode":"if (event instanceof FlowableEngineEvent) {\n    if (((FlowableEngineEvent) event).getProcessInstanceId() == null) {\n        throw new IllegalStateException(\"Message-throwing listener requires an event inside a process instance\");\n    }\n}","typeGuard":"boolean isExecutionScoped(FlowableEvent event) {\n    return event instanceof FlowableEngineEvent\n        && ((FlowableEngineEvent) event).getProcessInstanceId() != null;\n}","tryCatchPattern":"try {\n    dispatchEvent(event);\n} catch (ActivitiIllegalArgumentException e) {\n    if (e.getMessage().contains(\"not part of an ongoing process instance\")) {\n        logger.warn(\"Skipped message throw: event not execution-scoped\");\n    } else { throw e; }\n}","preventionTips":["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."],"tags":["bpmn","message-event","listener","process-instance"],"backgroundTag":"invalid-state-transition","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}