flowable/flowable-engine · error · FlowableIllegalArgumentException
The process definition with id ${processDefinitionId} has mo
Error message
The process definition with id ${processDefinitionId} has more than one event-registry start events based on manually registered subscriptions, which is currently not supported. What it means
When starting a process instance via an event-registry start event with manual correlation configuration, Flowable registers a start-event subscription per process definition. The engine supports at most ONE manually registered event-registry start event per process definition; RegisterProcessInstanceStartEventSubscriptionCmd.execute throws FlowableIllegalArgumentException when it encounters a second such start event while a subscription is already registered.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/RegisterProcessInstanceStartEventSubscriptionCmd.java:71
@Override
public EventSubscription execute(CommandContext commandContext) {
ProcessDefinition processDefinition = getLatestProcessDefinitionByKey(builder.getProcessDefinitionKey(), builder.getTenantId(), commandContext);
Process process = getProcess(processDefinition.getId(), commandContext);
EventSubscription eventSubscription = null;
List<StartEvent> startEvents = process.findFlowElementsOfType(StartEvent.class, false);
for (StartEvent startEvent : startEvents) {
// looking for a start event based on an event-registry event subscription
EventRegistryEventDefinition eventDefinition = EventRegistryEventDefinitionUtil.findOn(startEvent);
if (eventDefinition != null && StringUtils.isNotEmpty(eventDefinition.getEventDefinitionKey())) {
// looking for a dynamic, manually subscribed behavior of the event-registry start event
List<ExtensionElement> correlationConfiguration = startEvent.getExtensionElements().get(BpmnXMLConstants.START_EVENT_CORRELATION_CONFIGURATION);
if (correlationConfiguration != null && correlationConfiguration.size() > 0 &&
BpmnXMLConstants.START_EVENT_CORRELATION_MANUAL.equals(correlationConfiguration.get(0).getElementText())) {
// currently, only one event-registry start event is supported for manual subscriptions
if (eventSubscription != null) {
throw new FlowableIllegalArgumentException("The process definition with id " + processDefinition.getId()
+ " has more than one event-registry start events based on manually registered subscriptions, which is currently not supported.");
}
String eventDefinitionKey = eventDefinition.getEventDefinitionKey();
String correlationKey = generateCorrelationConfiguration(eventDefinitionKey, builder.getTenantId(),
builder.getCorrelationParameterValues(), commandContext);
eventSubscription = insertEventRegistryEvent(eventDefinitionKey, builder.isDoNotUpdateToLatestVersionAutomatically(), startEvent, processDefinition,
correlationKey, commandContext);
}
}
}
if (eventSubscription == null) {
throw new FlowableIllegalArgumentException("The process definition with id '" + processDefinition.getId()
+ "' does not have an event-registry based start event with a manual subscription behavior.");
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Keep at most one manually-correlated event-registry start event per process definition; split the second trigger into a separate process definition
- Change the second start event's correlation configuration from 'manual' to automatic/default correlation (remove the flowable:startEventCorrelationConfiguration extension or set it to a supported value)
- Restructure the model so one start event fans out via the event registry (e.g. catch the other messages after process start with intermediate event-registry catch events)
Example fix
<!-- before: two manually-correlated start events in one definition --> <startEvent id="startA"><extensionElements> <flowable:startEventCorrelationConfiguration>manual</flowable:startEventCorrelationConfiguration> </extensionElements></startEvent> <startEvent id="startB"><extensionElements> <flowable:startEventCorrelationConfiguration>manual</flowable:startEventCorrelationConfiguration> </extensionElements></startEvent> <!-- after: single manual start event; other trigger modeled as intermediate catch event --> <startEvent id="startA"><extensionElements> <flowable:startEventCorrelationConfiguration>manual</flowable:startEventCorrelationConfiguration> </extensionElements></startEvent> <intermediateCatchEvent id="catchB"><extensionElements> <flowable:eventRegistryEventDefinition eventDefinitionKey="msgB"/> </extensionElements></intermediateCatchEvent>
Defensive patterns
Strategy: validation
Validate before calling
long manualStartEvents = model.getBpmnModel().getMainProcess().getFlowElements().stream()
.filter(StartEvent.class::isInstance).map(StartEvent.class::cast)
.filter(se -> se.getExtensionElements()
.getOrDefault("startEventCorrelationConfiguration", Collections.emptyList())
.stream().anyMatch(e -> "manual".equals(e.getElementText())))
.count();
if (manualStartEvents > 1) throw new IllegalStateException("At most one manual event-registry start event allowed"); Type guard
boolean hasSingleManualStartEvent(BpmnModel model) {
long n = model.getMainProcess().getFlowElements().stream()
.filter(StartEvent.class::isInstance)
.map(StartEvent.class::cast)
.filter(se -> se.getExtensionElements()
.getOrDefault("startEventCorrelationConfiguration", Collections.emptyList())
.stream().anyMatch(e -> "manual".equals(e.getElementText())))
.count();
return n <= 1;
} Try / catch
try {
runtimeService.createProcessInstanceBuilder().start();
} catch (FlowableIllegalArgumentException e) {
if (e.getMessage().contains("more than one event-registry start events")) {
// fix the BPMN model: keep one manual start event, redeploy
}
throw e;
} Prevention
- Audit BPMN models at deploy time for multiple manually-correlated start events
- Model additional triggers as intermediate event-registry catch events
- Document the one-manual-start-event-per-definition limit for process designers
When it happens
Trigger: Deploying/starting a process definition whose BPMN model contains two or more event-registry start events whose <extensionElements> include flowable:startEventCorrelationConfiguration with value 'manual'; during execution of RegisterProcessInstanceStartEventSubscriptionCmd the loop finds eventSubscription already set for a second qualifying start event.
Common situations: Modeling multiple message/start events with manual correlation in one process definition (e.g. two different business messages that may both start the instance); copying a start event with correlation configuration to add a second trigger; upgrading Flowable and hitting a previously-tolerated model shape.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- CommandInvoker must be the last interceptor in the chain
- unsupported operation on configuration beans
- can't clear configuration beans
- can't search values in configuration beans
- Cannot change fixed value with
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/cd87dc50f6936066.
Report an issue: GitHub.