flowable/flowable-engine · error · FlowableException

getSuspendedExceptionMessagePrefix() + " a suspended " +…

Error message

getSuspendedExceptionMessagePrefix() + " a suspended " + execution

What it means

Flowable refuses to run commands extending NeedsActiveExecutionCmd against a suspended execution. The command first looks up the execution, then checks isSuspended(); if the execution (or its process instance) was suspended via RuntimeService.suspendProcessInstanceById or suspendExecution, the operation is aborted with a FlowableException.

Solutions

  1. Resume the instance first with runtimeService.activateProcessInstanceById(processInstanceId), then retry the command.
  2. Check suspension state before calling: inspect ExecutionEntity.isSuspended() via RuntimeService.createExecutionQuery().executionId(id).singleResult().isSuspended().
  3. If suspension is intentional, stop delivering signals/triggers to that instance and route them to a queue until reactivation.
  4. Catch FlowableException and handle the suspended-business-flow case explicitly in the caller.

Example fix

// before
runtimeService.trigger(executionId);
// after
Execution execution = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
if (execution != null && !execution.isSuspended()) {
    runtimeService.trigger(executionId);
}
Defensive patterns

Strategy: validation

Validate before calling

Execution exec = runtimeService.createExecutionQuery().executionId(executionId).singleResult();
if (exec != null && exec.isSuspended()) { throw new IllegalStateException("Execution is suspended"); }

Try / catch

try {
    runtimeService.trigger(executionId);
} catch (FlowableException e) {
    if (e.getMessage().contains("suspended")) {
        runtimeService.activateProcessInstanceById(processInstanceId);
        runtimeService.trigger(executionId); // retry once
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling trigger/signal/message commands on an execution whose process instance was put in SUSPENDED state (e.g. via RuntimeService.suspendProcessInstanceById or suspendProcessInstanceByKey).

Common situations: Admin suspended a process definition or instance for maintenance while in-flight messages/signals still arrive; job triggers firing against suspended instances; tests reusing suspended fixtures.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/ac6d799ac2197cc4. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/NeedsActiveExecutionCmd.java:52

    public NeedsActiveExecutionCmd(String executionId) {
        this.executionId = executionId;
    }

    @Override
    public T execute(CommandContext commandContext) {
        if (executionId == null) {
            throw new FlowableIllegalArgumentException("executionId is null");
        }

        ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager(commandContext).findById(executionId);

        if (execution == null) {
            throw new FlowableObjectNotFoundException("execution " + executionId + " doesn't exist", Execution.class);
        }

        if (execution.isSuspended()) {
            throw new FlowableException(getSuspendedExceptionMessagePrefix() + " a suspended " + execution);
        }

        return execute(commandContext, execution);
    }

    /**
     * Subclasses should implement this method. The provided {@link ExecutionEntity} is guaranteed to be active (ie. not suspended).
     */
    protected abstract T execute(CommandContext commandContext, ExecutionEntity execution);

    /**
     * Subclasses can override this to provide a more detailed exception message that will be thrown when the execution is suspended.
     */
    protected String getSuspendedExceptionMessagePrefix() {
        return "Cannot execute operation for";
    }

}

View on GitHub (pinned to d6d39ce1c6)