flowable/flowable-engine · error · ActivitiException

Cannot deploy process definition

Error message

Cannot deploy process definition '%s': there already is a message event subscription for the message with name '%s'.

What it means

A message name must be globally unique for message start events: the deployer checks the event subscription table (ACT_RU_EVENT_SUB) for existing start-event subscriptions (those with no processInstanceId) using the same message name. If one exists, the new deployment is rejected to avoid nondeterministic message correlation.

Solutions

  1. Delete the old process definition deployment that holds the conflicting message start subscription
  2. Use a unique message name for the new process definition
  3. Clean up orphaned rows in ACT_RU_EVENT_SUB if they belong to removed definitions
Defensive patterns

Strategy: validation

Validate before calling

List<EventSubscription> subs = runtimeService.createEventSubscriptionQuery()
    .eventName(messageName).eventType("message").list();
boolean conflict = subs.stream().anyMatch(s -> s.getProcessInstanceId() == null);

Try / catch

try {
    repositoryService.createDeployment().addClasspathResource(model).deploy();
} catch (org.activiti.engine.ActivitiException e) {
    if (e.getMessage().contains("already is a message event subscription")) {
        // delete the old deployment or rename the message
    }
}

Prevention

When it happens

Trigger: deploy -> addMessageEventSubscriptions when the new process definition's message start event name matches an existing start-event subscription in the database, typically created by a previously deployed process definition.

Common situations: Deploying a second, differently-keyed process that uses the same message name as an already deployed process; test environments sharing one database; failing to undeploy/delete an old definition that still holds the subscription.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/deployer/BpmnDeployer.java:434

                    List<MessageEventSubscriptionEntity> cachedSubscriptions = commandContext
                            .getDbSqlSession()
                            .findInCache(MessageEventSubscriptionEntity.class);
                    for (MessageEventSubscriptionEntity cachedSubscription : cachedSubscriptions) {
                        if (eventDefinition.getEventName().equals(cachedSubscription.getEventName())
                                && !subscriptionsForSameMessageName.contains(cachedSubscription)) {
                            subscriptionsForSameMessageName.add(cachedSubscription);
                        }
                    }
                    // remove subscriptions deleted in the same command
                    subscriptionsForSameMessageName = commandContext
                            .getDbSqlSession()
                            .pruneDeletedEntities(subscriptionsForSameMessageName);

                    for (EventSubscriptionEntity eventSubscriptionEntity : subscriptionsForSameMessageName) {
                        // throw exception only if there's already a subscription as start event
                        if (eventSubscriptionEntity.getProcessInstanceId() == null || eventSubscriptionEntity.getProcessInstanceId().isEmpty()) {
                            // the event subscription has no instance-id, so it's a message start event
                            throw new ActivitiException("Cannot deploy process definition '" + processDefinition.getResourceName()
                                    + "': there already is a message event subscription for the message with name '" + eventDefinition.getEventName() + "'.");
                        }
                    }

                    MessageEventSubscriptionEntity newSubscription = new MessageEventSubscriptionEntity();
                    newSubscription.setEventName(eventDefinition.getEventName());
                    newSubscription.setActivityId(eventDefinition.getActivityId());
                    newSubscription.setConfiguration(processDefinition.getId());
                    newSubscription.setProcessDefinitionId(processDefinition.getId());

                    if (processDefinition.getTenantId() != null) {
                        newSubscription.setTenantId(processDefinition.getTenantId());
                    }

                    newSubscription.insert();
                }
            }
        }

View on GitHub (pinned to d6d39ce1c6)