{"record":{"id":"9bffdeaa2b7aeae0","repo":"flowable/flowable-engine","slug":"cannot-throw-signal-event-eventname-because","errorCode":null,"errorMessage":"Cannot throw signal event '${eventName}' because ${execution} is suspended","messagePattern":"Cannot throw signal event '(.+?)' because (.+?) is suspended","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SignalEventReceivedCmd.java","lineNumber":87,"sourceCode":"    @Override\r\n    public Void execute(CommandContext commandContext) {\r\n\r\n        List<SignalEventSubscriptionEntity> signalEvents = null;\r\n\r\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\r\n        EventSubscriptionService eventSubscriptionService = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService();\r\n        if (executionId == null) {\r\n            signalEvents = eventSubscriptionService.findSignalEventSubscriptionsByEventName(eventName, tenantId);\r\n        } else {\r\n\r\n            ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager(commandContext).findById(executionId);\r\n\r\n            if (execution == null) {\r\n                throw new FlowableObjectNotFoundException(\"Cannot find execution with id '\" + executionId + \"'\", Execution.class);\r\n            }\r\n\r\n            if (execution.isSuspended()) {\r\n                throw new FlowableException(\"Cannot throw signal event '\" + eventName + \"' because \" + execution + \" is suspended\");\r\n            }\r\n\r\n            if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, execution.getProcessDefinitionId())) {\r\n                Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();\r\n                compatibilityHandler.signalEventReceived(eventName, executionId, payload, async, tenantId);\r\n                return null;\r\n            }\r\n\r\n            signalEvents = eventSubscriptionService.findSignalEventSubscriptionsByNameAndExecution(eventName, executionId);\r\n\r\n            if (signalEvents.isEmpty()) {\r\n                throw new FlowableException(execution + \" 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","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SignalEventReceivedCmd.java#L69-L105","documentation":"The target execution for a signal event exists but is suspended, and Flowable refuses to deliver the signal into a frozen execution. Signals are state-changing operations, so they are blocked while suspension is in effect.","triggerScenarios":"Calling runtimeService.signalEventReceived(eventName, executionId) on an execution suspended via suspendProcessInstanceById/DefinitionId or a suspend job definition.","commonSituations":"External events (payments, callbacks) arriving while an administrator suspended the process for maintenance; instances suspended because their process definition was suspended.","solutions":["Activate the instance with runtimeService.activateProcessInstanceById(execution.getProcessInstanceId()) before signaling.","Buffer the signal: store the event payload and deliver it after resumption (or via a job/retry).","Check execution.isSuspended() (or the suspended flag on the query result) and handle gracefully in the caller."],"exampleFix":"// before\nruntimeService.signalEventReceived(eventName, executionId);\n// after\nExecution e = runtimeService.createExecutionQuery().executionId(executionId).singleResult();\nif (e != null && !e.isSuspended()) {\n    runtimeService.signalEventReceived(eventName, executionId);\n}","handlingStrategy":"try-catch","validationCode":"Execution e = runtimeService.createExecutionQuery().executionId(executionId).singleResult();\nif (e != null && !e.isSuspended()) runtimeService.signalEventReceived(signalName, executionId);","typeGuard":null,"tryCatchPattern":"try {\n    runtimeService.signalEventReceived(signalName, executionId);\n} catch (FlowableException e) {\n    if (e.getMessage().contains(\"is suspended\")) {\n        pendingSignalStore.save(signalName, executionId); // deliver after activation\n    } else throw e;\n}","preventionTips":["Queue signals for suspended executions and flush on activation","Check the suspended flag on the Execution query result before signaling","Coordinate with admins: external events arriving during maintenance windows should be buffered"],"tags":["flowable","signal-event","suspended","invalid-state"],"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-14T11:17:12.474Z"}