{"record":{"id":"7cac5139a59dc273","repo":"flowable/flowable-engine","slug":"cannot-throw-signal-event-eventname-because-ex","errorCode":null,"errorMessage":"Cannot throw signal event '<eventName>' because execution '<executionId>' is suspended","messagePattern":"Cannot throw signal event '<eventName>' because execution '<executionId>' is suspended","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SignalEventReceivedCmd.java","lineNumber":82,"sourceCode":"\r\n    @Override\r\n    public Void execute(CommandContext commandContext) {\r\n\r\n        List<SignalEventSubscriptionEntity> signalEvents = null;\r\n\r\n        if (executionId == null) {\r\n            signalEvents = commandContext.getEventSubscriptionEntityManager().findSignalEventSubscriptionsByEventName(eventName, tenantId);\r\n\r\n        } else {\r\n\r\n            ExecutionEntity execution = commandContext.getExecutionEntityManager().findExecutionById(executionId);\r\n\r\n            if (execution == null) {\r\n                throw new ActivitiObjectNotFoundException(\"Cannot find execution with id '\" + executionId + \"'\", Execution.class);\r\n            }\r\n\r\n            if (execution.isSuspended()) {\r\n                throw new ActivitiException(\"Cannot throw signal event '\" + eventName\r\n                        + \"' because execution '\" + executionId + \"' is suspended\");\r\n            }\r\n\r\n            signalEvents = commandContext.getEventSubscriptionEntityManager().findSignalEventSubscriptionsByNameAndExecution(eventName, executionId);\r\n\r\n            if (signalEvents.isEmpty()) {\r\n                throw new ActivitiException(\"Execution '\" + executionId + \"' has not subscribed to a signal event with name '\" + eventName + \"'.\");\r\n            }\r\n        }\r\n\r\n        for (SignalEventSubscriptionEntity signalEventSubscriptionEntity : signalEvents) {\r\n            // We only throw the event to globally scoped signals.\r\n            // Process instance scoped signals must be thrown within the process itself\r\n            if (signalEventSubscriptionEntity.isGlobalScoped()) {\r\n                signalEventSubscriptionEntity.eventReceived(payload, async);\r\n            }\r\n        }\r\n\r","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SignalEventReceivedCmd.java#L64-L100","documentation":"SignalEventReceivedCmd throws ActivitiException when the execution referenced by executionId is suspended, preventing a signal event from being thrown into it. Suspended executions must not receive events until activated, so the command aborts, guarding the process state machine against modifications during suspension.","triggerScenarios":"Calling runtimeService.signalEventReceived(eventName, executionId) while the instance or execution was paused via suspendProcessInstanceById / suspendProcessInstanceByProcessDefinitionId.","commonSituations":"Maintenance suspension active when an external event (approval callback, message-queue listener) tries to deliver a signal; bulk suspension sweep racing with event delivery.","solutions":["Resume with runtimeService.activateProcessInstanceById(instanceId) before signaling.","Buffer the event externally (queue/DB) and deliver it once the instance is activated.","Check suspension state via ProcessInstanceQuery.suspended() and defer or discard the signal."],"exampleFix":"// before\nruntimeService.signalEventReceived(\"order-approved\", executionId);\n// after\nif (runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).suspended().count() == 0) {\n    runtimeService.signalEventReceived(\"order-approved\", executionId);\n} else {\n    // buffer event for delivery after activation\n}","handlingStrategy":"validation","validationCode":"boolean suspended = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).suspended().count() > 0;\nif (!suspended) runtimeService.signalEventReceived(eventName, executionId);","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.signalEventReceived(eventName, executionId);\n} catch (ActivitiException e) {\n    logger.warn(\"Execution {} suspended; buffering signal {}\", executionId, eventName);\n    eventBuffer.add(new PendingSignal(eventName, executionId));\n}","preventionTips":["Subscribe external listeners to the suspension lifecycle so event delivery can be paused.","Buffer inbound events while instances are under maintenance suspension."],"tags":["signal-event","suspended-state","workflow"],"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"}