flowable/flowable-engine · error · FlowableException
has not subscribed to a signal event with name ' '.
Error message
${execution} has not subscribed to a signal event with name '${eventName}'. What it means
The given execution exists and is active, but no signal event subscription with the supplied name is registered on it. Signals delivered to a specific execution must match a signal boundary/intermediate-catch event waiting in that execution; otherwise Flowable throws instead of silently dropping the event.
Solutions
- Confirm the BPMN node is a signal catch/boundary event and its signal name exactly matches the eventName passed (case-sensitive).
- Find valid targets with runtimeService.createExecutionQuery().signalEventSubscriptionName(eventName).list() and use one of those execution ids.
- Handle double-delivery: query the subscription first and skip if absent (idempotent signaling).
Example fix
// before
runtimeService.signalEventReceived("OrderPaid", executionId);
// after
if (!runtimeService.createExecutionQuery().executionId(executionId)
.signalEventSubscriptionName("OrderPaid").list().isEmpty()) {
runtimeService.signalEventReceived("OrderPaid", executionId);
} Defensive patterns
Strategy: validation
Validate before calling
boolean waiting = !runtimeService.createExecutionQuery()
.executionId(executionId)
.signalEventSubscriptionName(signalName).list().isEmpty();
if (waiting) runtimeService.signalEventReceived(signalName, executionId); Try / catch
try {
runtimeService.signalEventReceived(signalName, executionId);
} catch (FlowableException e) {
if (e.getMessage().contains("has not subscribed")) {
log.info("No active subscription for signal {} on {}", signalName, executionId);
} else throw e;
} Prevention
- Match signal names exactly (case-sensitive) between BPMN and caller; share them as constants
- Discover target executions via ExecutionQuery.signalEventSubscriptionName(...) instead of assuming the parent execution
- Guard against duplicate delivery — the first signal removes the subscription
When it happens
Trigger: Calling runtimeService.signalEventReceived(eventName, executionId) where the execution is not currently waiting at a signal catch event with that name (wrong name, event already fired, or execution is a parent not at the wait state).
Common situations: Typo or case mismatch in the signal name between BPMN and caller; duplicate signal delivery after the first one already advanced the token; signaling the process instance execution instead of the execution waiting at the boundary event.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- At least one correlation parameter value must be provided…
- At least one correlation parameter value must be provided…
- Cannot find execution with id
- Cannot start process instance by message: no subscription…
- Cannot throw signal event
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8542e3cd0f925740.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SignalEventReceivedCmd.java:99
if (execution == null) {
throw new FlowableObjectNotFoundException("Cannot find execution with id '" + executionId + "'", Execution.class);
}
if (execution.isSuspended()) {
throw new FlowableException("Cannot throw signal event '" + eventName + "' because " + execution + " is suspended");
}
if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, execution.getProcessDefinitionId())) {
Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
compatibilityHandler.signalEventReceived(eventName, executionId, payload, async, tenantId);
return null;
}
signalEvents = eventSubscriptionService.findSignalEventSubscriptionsByNameAndExecution(eventName, executionId);
if (signalEvents.isEmpty()) {
throw new FlowableException(execution + " has not subscribed to a signal event with name '" + eventName + "'.");
}
}
for (SignalEventSubscriptionEntity signalEventSubscriptionEntity : signalEvents) {
// We only throw the event to globally scoped signals.
// Process instance scoped signals must be thrown within the process itself
if (signalEventSubscriptionEntity.isGlobalScoped()) {
if (executionId == null && Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, signalEventSubscriptionEntity.getProcessDefinitionId())) {
Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
compatibilityHandler.signalEventReceived(signalEventSubscriptionEntity, payload, async);
} else {
processEngineConfiguration.getEventDispatcher().dispatchEvent(
FlowableEventBuilder.createSignalEvent(FlowableEngineEventType.ACTIVITY_SIGNALED, signalEventSubscriptionEntity.getActivityId(), eventName,
payload, signalEventSubscriptionEntity.getExecutionId(), signalEventSubscriptionEntity.getProcessInstanceId(),
signalEventSubscriptionEntity.getProcessDefinitionId()), processEngineConfiguration.getEngineCfgKey());
View on GitHub (pinned to d6d39ce1c6)