flowable/flowable-engine · warning

Cannot have more than one message event subscription with…

Error message

Cannot have more than one message event subscription with name '{}' for scope '{}'

What it means

addEventSubscriptionDeclaration() warns when a scope already contains a message event subscription with the same event name and start-event flag. The duplicate subscription is still added, but only one can be triggered deterministically, signaling a modeling mistake.

Solutions

  1. Give each message event subscription a unique message name within its scope
  2. Remove the duplicate message event declaration
  3. If separate processes need the same message, place them in scopes where the subscription names do not collide, or correlate deliberately with distinct names

Example fix

// before
<messageEventDefinition messageRef="orderReceived"/> (twice in same scope)
// after
<messageEventDefinition messageRef="orderReceived"/>
<messageEventDefinition messageRef="orderAmended"/>
Defensive patterns

Strategy: validation

Validate before calling

// Detect duplicate message names per scope before deployment
Map<String,Integer> counts = new HashMap<>();
for (MessageEventDefinition def : collectMessageDefinitions(process)) {
    counts.merge(def.getMessageRef(), 1, Integer::sum);
}
counts.forEach((name,c) -> { if (c > 1) throw new IllegalArgumentException("Duplicate message name: " + name); });

Prevention

When it happens

Trigger: Two message start events (or two message boundary/intermediate catch events) in the same scope declare the same message name — e.g. duplicate <messageEventDefinition messageRef="x"/> — detected in AbstractBpmnParseHandler.addEventSubscriptionDeclaration().

Common situations: Copy-pasted message start events in a process (or two executable processes sharing a message name in the same deployment scope); merging process models without renaming message refs.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/handler/AbstractBpmnParseHandler.java:151

        }
        return executionListener;
    }

    @SuppressWarnings("unchecked")
    protected void addEventSubscriptionDeclaration(BpmnParse bpmnParse, EventSubscriptionDeclaration subscription, EventDefinition parsedEventDefinition, ScopeImpl scope) {
        List<EventSubscriptionDeclaration> eventDefinitions = (List<EventSubscriptionDeclaration>) scope.getProperty(PROPERTYNAME_EVENT_SUBSCRIPTION_DECLARATION);
        if (eventDefinitions == null) {
            eventDefinitions = new ArrayList<>();
            scope.setProperty(PROPERTYNAME_EVENT_SUBSCRIPTION_DECLARATION, eventDefinitions);
        } else {
            // if this is a message event, validate that it is the only one with the provided name for this scope
            if ("message".equals(subscription.getEventType())) {
                for (EventSubscriptionDeclaration eventDefinition : eventDefinitions) {
                    if ("message".equals(eventDefinition.getEventType())
                            && eventDefinition.getEventName().equals(subscription.getEventName())
                            && eventDefinition.isStartEvent() == subscription.isStartEvent()) {

                        LOGGER.warn("Cannot have more than one message event subscription with name '{}' for scope '{}'", subscription.getEventName(), scope.getId());
                    }
                }
            }
        }
        eventDefinitions.add(subscription);
    }

    protected String getPrecedingEventBasedGateway(BpmnParse bpmnParse, IntermediateCatchEvent event) {
        String eventBasedGatewayId = null;
        for (SequenceFlow sequenceFlow : event.getIncomingFlows()) {
            FlowElement sourceElement = bpmnParse.getBpmnModel().getFlowElement(sequenceFlow.getSourceRef());
            if (sourceElement instanceof EventGateway) {
                eventBasedGatewayId = sourceElement.getId();
                break;
            }
        }
        return eventBasedGatewayId;
    }

View on GitHub (pinned to d6d39ce1c6)