{"record":{"id":"688f3b1fc6e0bafb","repo":"flowable/flowable-engine","slug":"cannot-throw-process-instance-scoped-signal-since-688f3b","errorCode":null,"errorMessage":"Cannot throw process-instance scoped signal, since the dispatched event is not part of an ongoing process instance","messagePattern":"Cannot throw process-instance scoped signal, 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/SignalThrowingEventListener.java","lineNumber":43,"sourceCode":"\n/**\n * An {@link FlowableEventListener} that throws a signal event when an event is dispatched to it.\n * \n * @author Frederik Heremans\n * \n */\npublic class SignalThrowingEventListener extends BaseDelegateEventListener {\n\n    protected String signalName;\n    protected boolean processInstanceScope = true;\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 && processInstanceScope) {\n                throw new ActivitiIllegalArgumentException(\n                        \"Cannot throw process-instance scoped signal, since the dispatched event is not part of an ongoing process instance\");\n            }\n\n            CommandContext commandContext = Context.getCommandContext();\n            List<SignalEventSubscriptionEntity> subscriptionEntities = null;\n            if (processInstanceScope) {\n                subscriptionEntities = commandContext.getEventSubscriptionEntityManager()\n                        .findSignalEventSubscriptionsByProcessInstanceAndEventName(engineEvent.getProcessInstanceId(), signalName);\n            } else {\n                String tenantId = null;\n                if (engineEvent.getProcessDefinitionId() != null) {\n                    ProcessDefinition processDefinition = commandContext.getProcessEngineConfiguration()\n                            .getDeploymentManager().findDeployedProcessDefinitionById(engineEvent.getProcessDefinitionId());\n                    tenantId = processDefinition.getTenantId();\n                }\n                subscriptionEntities = commandContext.getEventSubscriptionEntityManager()\n                        .findSignalEventSubscriptionsByEventName(signalName, tenantId);\n            }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/SignalThrowingEventListener.java#L25-L61","documentation":"Thrown as ActivitiIllegalArgumentException when a SignalThrowingEventListener is configured with processInstanceScope=true but the dispatched FlowableEngineEvent has a null processInstanceId. A process-instance-scoped signal must be thrown within an ongoing process instance, so the engine rejects the event dispatch.","triggerScenarios":"onEvent is invoked with isValidEvent(event) true and event instanceof FlowableEngineEvent, processInstanceScope is true, and engineEvent.getProcessInstanceId() == null — e.g. the listener is subscribed to an engine-level or deployment event.","commonSituations":"Configuring a signal-throwing event listener with processInstanceScope=\"true\" on events that fire outside any process instance; listeners registered globally in ProcessEngineConfiguration eventListeners rather than in a process definition; copy-paste of listener config from an instance-scoped use case.","solutions":["Register the process-instance-scoped signal listener only for execution-related events (events that carry a processInstanceId).","Set processInstanceScope=\"false\" (or omit it) if the signal is meant to be globally scoped — global signals do not require a process instance.","Guard in wrapping code: only dispatch to the listener when engineEvent.getProcessInstanceId() != null.","Move the listener declaration from global engine configuration into the specific process definition where the event occurs."],"exampleFix":"// before\n<activiti:eventListener events=\"ENGINE_CLOSED\" eventType=\"signal-throwing\" signalName=\"mySignal\" processInstanceScope=\"true\"/>\n\n// after: use global scope for engine-level events, or bind to an in-execution event\n<activiti:eventListener events=\"ACTIVITY_SIGNALLED\" eventType=\"signal-throwing\" signalName=\"mySignal\" processInstanceScope=\"true\"/>","handlingStrategy":"validation","validationCode":"if (processInstanceScope && event instanceof FlowableEngineEvent\n        && ((FlowableEngineEvent) event).getProcessInstanceId() == null) {\n    throw new IllegalStateException(\"Process-instance-scoped signal requires an in-execution event\");\n}","typeGuard":"boolean canThrowInstanceScopedSignal(FlowableEvent event, boolean processInstanceScope) {\n    return !processInstanceScope\n        || (event instanceof FlowableEngineEvent\n            && ((FlowableEngineEvent) event).getProcessInstanceId() != null);\n}","tryCatchPattern":"try {\n    dispatchEvent(event);\n} catch (ActivitiIllegalArgumentException e) {\n    if (e.getMessage().contains(\"process-instance scoped signal\")) {\n        logger.warn(\"Signal dispatch skipped: no process instance on event\");\n    } else { throw e; }\n}","preventionTips":["Only set processInstanceScope=\"true\" when the listener event always carries a processInstanceId.","Use global signal scope (default) for engine-level events.","Declare signal-throwing listeners inside the process definition, not in global engine event listeners, when instance-scoped."],"tags":["bpmn","signal-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"}