flowable/flowable-engine · error · FlowableIllegalArgumentException

Signal name is required

Error message

Signal name is required

What it means

FlowableIllegalArgumentException thrown by ExecutionResource.performExecutionAction when the action is 'signal-event-received' but signalName is null. This per-execution endpoint delivers a signal to a specific execution waiting at a signal-catching event; the signal name identifies which event to fire.

Solutions

  1. Add "signalName" to the request body with the exact signal name from the BPMN model.
  2. Verify the JSON key spelling/casing is 'signalName'.
  3. If you meant to just continue a waiting execution without an event, use action "trigger" instead (no signalName needed).
  4. Ensure the execution is actually waiting at a signal-catching event with that name, otherwise the next call will fail with a different error.

Example fix

// before
{"action": "signal-event-received"}
// after
{"action": "signal-event-received", "signalName": "paymentReceived"}
Defensive patterns

Strategy: validation

Validate before calling

if (body.action === 'signal-event-received' && (!body.signalName || typeof body.signalName !== 'string')) {
  throw new Error(`POST /runtime/executions/${executionId} requires "signalName" for action signal-event-received`);
}

Type guard

function isSignalRequest(b: { action?: string; signalName?: unknown }): b is { action: 'signal-event-received'; signalName: string } {
  return b.action === 'signal-event-received' && typeof b.signalName === 'string' && b.signalName.length > 0;
}

Try / catch

try {
  await restClient.post(`/runtime/executions/${executionId}`, body);
} catch (e) {
  if (e.response && e.response.status === 400 && /Signal name is required/.test(e.response.data && e.response.data.message || '')) {
    console.error('Add "signalName" to the execution action request body');
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /runtime/executions/{executionId} with body {"action":"signal-event-received"} and no (or null) signalName field.

Common situations: Clients migrating from the collection endpoint forgetting the payload shape; building the body dynamically where the signal name variable is null; typos like 'signal-name' in JSON keys.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — 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/91ef1762aa47aba4. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ExecutionResource.java:79

        Execution execution = getExecutionFromRequest(executionId);
        
        if (restApiInterceptor != null) {
            restApiInterceptor.doExecutionActionRequest(execution, actionRequest);
        }

        if (ExecutionActionRequest.ACTION_SIGNAL.equals(actionRequest.getAction())
                || ExecutionActionRequest.ACTION_TRIGGER.equals(actionRequest.getAction())) {
            if (actionRequest.getTransientVariables() != null && actionRequest.getVariables() != null) {
                runtimeService.trigger(execution.getId(), getVariablesToSet(actionRequest.getVariables()), getVariablesToSet(actionRequest.getTransientVariables()));
            } else if (actionRequest.getVariables() != null) {
                runtimeService.trigger(execution.getId(), getVariablesToSet(actionRequest.getVariables()));
            } else {
                runtimeService.trigger(execution.getId());
            }
            
        } else if (ExecutionActionRequest.ACTION_SIGNAL_EVENT_RECEIVED.equals(actionRequest.getAction())) {
            if (actionRequest.getSignalName() == null) {
                throw new FlowableIllegalArgumentException("Signal name is required");
            }
            if (actionRequest.getVariables() != null) {
                runtimeService.signalEventReceived(actionRequest.getSignalName(), execution.getId(), getVariablesToSet(actionRequest.getVariables()));
            } else {
                runtimeService.signalEventReceived(actionRequest.getSignalName(), execution.getId());
            }
            
        } else if (ExecutionActionRequest.ACTION_MESSAGE_EVENT_RECEIVED.equals(actionRequest.getAction())) {
            if (actionRequest.getMessageName() == null) {
                throw new FlowableIllegalArgumentException("Message name is required");
            }
            if (actionRequest.getVariables() != null) {
                runtimeService.messageEventReceived(actionRequest.getMessageName(), execution.getId(), getVariablesToSet(actionRequest.getVariables()));
            } else {
                runtimeService.messageEventReceived(actionRequest.getMessageName(), execution.getId());
            }
            
        } else {

View on GitHub (pinned to d6d39ce1c6)