flowable/flowable-engine · error · FlowableException

No message start event found for process definition

Error message

No message start event found for process definition ${id} and message name ${messageName}

What it means

Thrown when starting a process instance by message and no StartEvent in the resolved process model has a MessageEventDefinition whose message name matches the given messageName. The engine cannot determine which start event to use.

Solutions

  1. Match the messageName string exactly to the name of the <message> referenced by the start event in the BPMN XML.
  2. Add a <startEvent><messageEventDefinition messageRef="..."/></startEvent> plus the <message> declaration and redeploy.
  3. Check you resolved the right definition (key/tenantId) — pass tenantId if messages are tenant-scoped.
  4. Use RuntimeService.createProcessDefinitionQuery().processDefinitionKey(key) to inspect the active version and confirm it contains the message start event.

Example fix

// before
runtimeService.startProcessInstanceByMessage("orderRecieved", vars); // typo
// after
// <message id="orderReceivedMsg" name="orderReceived"/>
runtimeService.startProcessInstanceByMessage("orderReceived", vars);
Defensive patterns

Strategy: validation

Validate before calling

BpmnModel model = repositoryService.getBpmnModel(def.getId());
boolean hasMsgStart = model.getMainProcess().getFlowElements().stream()
    .filter(org.flowable.bpmn.model.StartEvent.class::isInstance)
    .map(fe -> (org.flowable.bpmn.model.StartEvent) fe)
    .flatMap(se -> se.getEventDefinitions().stream())
    .anyMatch(ed -> ed instanceof org.flowable.bpmn.model.MessageEventDefinition
        && messageName.equals(((org.flowable.bpmn.model.MessageEventDefinition) ed).getMessageName()));
if (!hasMsgStart) throw new IllegalArgumentException("No message start event '" + messageName + "' on " + def.getId());

Type guard

public static boolean isMessageStartEvent(StartEvent se, String messageName) {
    return se.getEventDefinitions().stream()
        .filter(MessageEventDefinition.class::isInstance)
        .map(MessageEventDefinition.class::cast)
        .anyMatch(ed -> messageName.equals(ed.getMessageName()));
}

Try / catch

try {
    runtimeService.startProcessInstanceByMessage(messageName, vars);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("No message start event found")) {
        throw new IllegalArgumentException("Message '" + messageName + "' has no start event in the active definition", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: RuntimeService.startProcessInstanceByMessage(messageName, ...) where messageName is not declared on any <messageStartEvent> of the process definition resolved (by key or tenant).

Common situations: Message name mismatch between the BPMN <message name="..."> and the caller; missing <message> declaration in the model; a new process version dropped the message start event; wrong tenant — another tenant's definition has the event but the resolved one does not.

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


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/ProcessInstanceHelper.java:159

        if (process == null) {
            throw new FlowableException("Cannot start process instance. Process model " + processDefinition.getName() + " (id = " + processDefinition.getId() + ") could not be found");
        }

        FlowElement initialFlowElement = null;
        for (FlowElement flowElement : process.getFlowElements()) {
            if (flowElement instanceof StartEvent startEvent) {
                if (CollectionUtil.isNotEmpty(startEvent.getEventDefinitions()) && startEvent.getEventDefinitions()
                        .get(0) instanceof MessageEventDefinition messageEventDefinition) {
                    String actualMessageName = EventDefinitionExpressionUtil.determineMessageName(commandContext, messageEventDefinition, processDefinition);
                    if (Objects.equals(actualMessageName, messageName)) {
                        initialFlowElement = flowElement;
                        break;
                    }
                }
            }
        }
        if (initialFlowElement == null) {
            throw new FlowableException("No message start event found for process definition " + processDefinition.getId() + " and message name " + messageName);
        }

        return createAndStartProcessInstanceWithInitialFlowElement(processDefinition, businessKey, businessStatus, null, null, null, initialFlowElement,
                process, variables, transientVariables, callbackId, callbackType, referenceId, referenceType, ownerId, assigneeId, null, true);
    }
    
    public ProcessInstance createAndStartProcessInstanceWithInitialFlowElement(ProcessDefinition processDefinition,
            String businessKey, String businessStatus, String processInstanceName, FlowElement initialFlowElement, Process process,
            Map<String, Object> variables,
            Map<String, Object> transientVariables, String ownerId, String assigneeId, boolean startProcessInstance) {
        
        return createAndStartProcessInstanceWithInitialFlowElement(processDefinition, businessKey, businessStatus, processInstanceName, null, null,
                initialFlowElement, process, variables, transientVariables, null, null, null, null,
                ownerId, assigneeId, null, startProcessInstance);
    }

    public ProcessInstance createAndStartProcessInstanceWithInitialFlowElement(ProcessDefinition processDefinition,
            String businessKey, String businessStatus, String processInstanceName,

View on GitHub (pinned to d6d39ce1c6)