flowable/flowable-engine · error · FlowableIllegalArgumentException

Cannot throw process-instance scoped signal, since the dispa

Error message

Cannot throw process-instance scoped signal, since the dispatched event is not part of an ongoing process instance

What it means

SignalThrowingEventListener.onEvent throws this FlowableIllegalArgumentException when a signal is configured with processInstanceScope=true but the dispatched engine event has a null processInstanceId, so a process-instance-scoped signal cannot be delivered.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/helper/SignalThrowingEventListener.java:46

import org.flowable.eventsubscription.service.impl.persistence.entity.SignalEventSubscriptionEntity;

/**
 * An {@link FlowableEventListener} that throws a signal event when an event is dispatched to it.
 * 
 * @author Frederik Heremans
 * 
 */
public class SignalThrowingEventListener extends BaseDelegateEventListener {

    protected String signalName;
    protected boolean processInstanceScope = true;

    @Override
    public void onEvent(FlowableEvent event) {
        if (isValidEvent(event) && event instanceof FlowableEngineEvent engineEvent) {

            if (engineEvent.getProcessInstanceId() == null && processInstanceScope) {
                throw new FlowableIllegalArgumentException("Cannot throw process-instance scoped signal, since the dispatched event is not part of an ongoing process instance");
            }

            CommandContext commandContext = Context.getCommandContext();
            ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
            EventSubscriptionService eventSubscriptionService = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService();
            List<SignalEventSubscriptionEntity> subscriptionEntities = null;
            if (processInstanceScope) {
                subscriptionEntities = eventSubscriptionService.findSignalEventSubscriptionsByProcessInstanceAndEventName(engineEvent.getProcessInstanceId(), signalName);
            } else {
                String tenantId = null;
                if (engineEvent.getProcessDefinitionId() != null) {
                    ProcessDefinition processDefinition = processEngineConfiguration.getDeploymentManager()
                            .findDeployedProcessDefinitionById(engineEvent.getProcessDefinitionId());
                    tenantId = processDefinition.getTenantId();
                }
                subscriptionEntities = eventSubscriptionService.findSignalEventSubscriptionsByEventName(signalName, tenantId);
            }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Register the listener only for event types that carry a processInstanceId, or add a wrapper listener that filters on event.getProcessInstanceId() != null.
  2. If the signal should be global (all process instances), set processInstanceScope=false so the execution-scoped branch is used.
  3. Trigger the signal via runtimeService.signalEventReceived with explicit delivery semantics if a specific subscription is targeted.
  4. Audit listener XML config: ensure 'scope' attribute matches the events the listener is bound to.

Example fix

// before
<flowable:event-listener events="*" class="SignalThrowingEventListener" scope="processInstance" />

// after
<flowable:event-listener events="ACTIVITY_SIGNAL_WAITING,JOB_EXECUTION_SUCCESS" class="SignalThrowingEventListener" scope="processInstance" />
Defensive patterns

Strategy: type-guard

Validate before calling

if (processInstanceScope && (event == null || !(event instanceof FlowableEngineEvent)
        || ((FlowableEngineEvent) event).getProcessInstanceId() == null)) {
    throw new IllegalArgumentException("process-scoped signal requires an engine event with processInstanceId");
}

Type guard

static boolean supportsProcessScopeSignal(FlowableEvent event) {
    return event instanceof FlowableEngineEvent && ((FlowableEngineEvent) event).getProcessInstanceId() != null;
}

Try / catch

try {
    listener.onEvent(event);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("process-instance scoped signal")) {
        logger.warn("ignored process-scoped signal for event {}", event.getType());
    }
}

Prevention

When it happens

Trigger: A 'signal' event listener with processInstanceScope=true receives a FlowableEngineEvent whose getProcessInstanceId() is null — engine/deployment-level events, or events fired outside a running process instance.

Common situations: Global listeners reacting to all FlowableEventType values including engine events; signals thrown on process-start events before the instance id is assigned (rare) or on job/entity events outside process scope; copy-pasted listener config where scope was changed to process-instance but event source wasn't.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/0118ac524cd1dfe7. Report an issue: GitHub.