{"record":{"id":"80e8e8f6ea1c42bc","repo":"flowable/flowable-engine","slug":"couldn-t-process-signal-signalname-on-activity","errorCode":null,"errorMessage":"couldn't process signal '<signalName>' on activity '<activityId>': <cause>","messagePattern":"couldn't process signal '<signalName>' on activity '<activityId>': <cause>","errorType":"exception","errorClass":"PvmException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java","lineNumber":467,"sourceCode":"            String signalledActivityId = activity.getId();\n            activityBehavior.signal(this, signalName, signalData);\n\n            // If needed, dispatch an event indicating an activity was signalled\n            boolean isUserTask = (activityBehavior instanceof UserTaskActivityBehavior)\n                    || ((activityBehavior instanceof MultiInstanceActivityBehavior)\n                    && ((MultiInstanceActivityBehavior) activityBehavior).getInnerActivityBehavior() instanceof UserTaskActivityBehavior);\n\n            if (!isUserTask && Context.getProcessEngineConfiguration() != null\n                    && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {\n                Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createSignalEvent(\n                        FlowableEngineEventType.ACTIVITY_SIGNALED, signalledActivityId, signalName, signalData, this.id, this.processInstanceId, this.processDefinitionId),\n                        EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);\n            }\n\n        } catch (RuntimeException e) {\n            throw e;\n        } catch (Exception e) {\n            throw new PvmException(\"couldn't process signal '\" + signalName + \"' on activity '\" + activity.getId() + \"': \" + e.getMessage(), e);\n        }\n    }\n\n    @Override\n    public void take(PvmTransition transition) {\n        take(transition, true);\n    }\n\n    /**\n     * @param fireActivityCompletionEvent This method can be called from other places (like {@link #takeAll(List, List)}), where the event is already fired. In that case, false is passed an no second event is fired.\n     */\n    @Override\n    public void take(PvmTransition transition, boolean fireActivityCompletionEvent) {\n\n        if (fireActivityCompletionEvent) {\n            fireActivityCompletedEvent();\n        }\n","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/ExecutionEntity.java#L449-L485","documentation":"PvmException thrown by ExecutionEntity.signal when the process virtual machine fails to deliver a signal to the current activity. Any non-runtime exception during signaling (waiting-state continuation, event triggering) is wrapped into this message carrying the signal name, activity id, and cause message. It indicates the wait state could not be continued — the underlying cause is the real problem.","triggerScenarios":"Calling execution.signal(signalName, payload) or completing a wait state (receive task, user task via PVM internals, executionListener-triggered event) where the signaled activity's behavior throws a checked exception, e.g., a failing ExecutionListener, invalid event subscription, or a delegate throwing an Exception.","commonSituations":"Signaling an execution that has migrated to another activity, a delegate listener configured with a class that fails at runtime, sending a signal payload of the wrong type to a receive task, or triggering an event the activity is not actually waiting for.","solutions":["Inspect the wrapped cause (e.getCause()) — the PvmException message only carries cause.getMessage(); fix the underlying exception first","Verify the execution is actually waiting at the activity being signaled and that the signal/event name matches the wait state's subscription","Check any ExecutionListener/delegate classes on the signaled activity for bugs (constructor access, missing classes, thrown exceptions)","Log execution.getId() and activity id, and confirm the process state in the database before retrying"],"exampleFix":"// before\nexecution.signal(\"resume\", null); // cause hidden\n// after\ntry {\n    execution.signal(\"resume\", null);\n} catch (PvmException e) {\n    Throwable cause = e.getCause();\n    log.error(\"Signal failed on activity: \" + e.getMessage(), cause);\n    throw cause instanceof RuntimeException ? (RuntimeException) cause : e;\n}","handlingStrategy":"try-catch","validationCode":"// confirm the execution is waiting where you expect before signaling\nExecution e = runtimeService.createExecutionQuery()\n    .executionId(executionId).activityId(expectedActivityId).singleResult();\nif (e == null) throw new IllegalStateException(\"Execution not waiting at \" + expectedActivityId);","typeGuard":null,"tryCatchPattern":"try {\n    execution.signal(signalName, signalData);\n} catch (PvmException e) {\n    Throwable cause = e.getCause();\n    log.error(\"Signal '{}' on activity failed: {}\", signalName, e.getMessage(), cause);\n    throw cause instanceof RuntimeException ? (RuntimeException) cause : new RuntimeException(cause);\n}","preventionTips":["Always inspect getCause() — the message hides the root failure","Match signal/event names exactly to the wait state's declaration","Validate delegate/listener classes load and run before production","Re-query execution state before signaling after concurrent modifications"],"tags":["pvm","signal","execution","wrapped-exception"],"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"}