{"record":{"id":"1910290da83f8246","repo":"flowable/flowable-engine","slug":"execution-does-not-have-a-subscription-to-a-me","errorCode":null,"errorMessage":"execution + \" does not have a subscription to a message event with name '\" + messageName + \"'\"","messagePattern":"execution \\+ \" does not have a subscription to a message event with name '\" \\+ messageName \\+ \"'\"","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/MessageEventReceivedCmd.java","lineNumber":82,"sourceCode":"\r\n    @Override\r\n    protected Void execute(CommandContext commandContext, ExecutionEntity execution) {\r\n        if (messageName == null) {\r\n            throw new FlowableIllegalArgumentException(\"messageName cannot be null\");\r\n        }\r\n\r\n        if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, execution.getProcessDefinitionId())) {\r\n            Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();\r\n            compatibilityHandler.messageEventReceived(messageName, executionId, payload, async);\r\n            return null;\r\n        }\r\n\r\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\r\n        EventSubscriptionService eventSubscriptionService = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService();\r\n        List<EventSubscriptionEntity> eventSubscriptions = eventSubscriptionService.findEventSubscriptionsByNameAndExecution(MessageEventHandler.EVENT_HANDLER_TYPE, messageName, executionId);\r\n\r\n        if (eventSubscriptions.isEmpty()) {\r\n            throw new FlowableException(execution + \" does not have a subscription to a message event with name '\" + messageName + \"'\");\r\n        }\r\n\r\n        // there can be only one:\r\n        EventSubscriptionEntity eventSubscriptionEntity = eventSubscriptions.get(0);\r\n        EventSubscriptionUtil.eventReceived(eventSubscriptionEntity, payload, async);\r\n\r\n        return null;\r\n    }\r\n\r\n    @Override\r\n    protected String getSuspendedExceptionMessagePrefix() {\r\n        return \"Cannot receive message for\";\r\n    }\r\n}\r\n","sourceCodeStart":64,"sourceCodeEnd":97,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/MessageEventReceivedCmd.java#L64-L97","documentation":"When delivering a message, MessageEventReceivedCmd queries event subscriptions of type message by name and executionId. If none exist it throws FlowableException '<execution> does not have a subscription to a message event with name '<name>''. The execution is not currently waiting at a message event with that name, so there is nothing to deliver to.","triggerScenarios":"Calling runtimeService.messageEventReceived(messageName, executionId) where the execution has already passed the message event, the name doesn't match the subscription, or the executionId points to a scope with no message subscription.","commonSituations":"Race conditions where the message arrives twice and the first delivery moved the process past the boundary event; mistyped message names; triggering on the wrong execution id (e.g. process instance id instead of the waiting execution id); timeouts already cancelled the subscription.","solutions":["Find a valid waiting execution with runtimeService.createExecutionQuery().processInstanceId(pid).messageEventSubscriptionName(name).singleResult() and use its id.","Verify the message name matches the BPMN element's messageRef/name exactly.","Guard against double delivery with idempotency checks before triggering.","Catch FlowableException (or FlowableException subtype) around messageEventReceived and treat 'no subscription' as 'message too late'."],"exampleFix":"// before\nruntimeService.messageEventReceived(\"orderReceived\", processInstanceId);\n// after\nExecution exec = runtimeService.createExecutionQuery()\n    .processInstanceId(pid)\n    .messageEventSubscriptionName(\"orderReceived\")\n    .singleResult();\nif (exec != null) {\n    runtimeService.messageEventReceived(\"orderReceived\", exec.getId());\n}","handlingStrategy":"validation","validationCode":"Execution exec = runtimeService.createExecutionQuery()\n    .processInstanceId(pid)\n    .messageEventSubscriptionName(messageName)\n    .singleResult();\nif (exec == null) {\n    log.info(\"No waiting subscription for message {} — skipping delivery\", messageName);\n    return;\n}","typeGuard":"boolean hasMessageSubscription(String pid, String name) {\n    return runtimeService.createExecutionQuery()\n        .processInstanceId(pid)\n        .messageEventSubscriptionName(name)\n        .count() > 0;\n}","tryCatchPattern":"try {\n    runtimeService.messageEventReceived(messageName, executionId, payload);\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"does not have a subscription\")) {\n        log.warn(\"Message {} arrived too late for execution {}\", messageName, executionId);\n        return;\n    }\n    throw e;\n}","preventionTips":["Resolve the waiting execution id via ExecutionQuery, never assume the process instance id","Make message delivery idempotent to survive duplicates","Handle boundary-event timeouts which remove subscriptions asynchronously"],"tags":["flowable","message-event","race-condition","event-subscription"],"backgroundTag":"invalid-state-transition","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}