flowable/flowable-engine · error · FlowableException

Sequential ad-hoc sub process in ${execution} already has an

Error message

Sequential ad-hoc sub process in ${execution} already has an active execution

What it means

In an ad-hoc subprocess with sequential ordering, only one child execution may be active at a time. execute() throws FlowableException when executions already exist under the ad-hoc subprocess, refusing to start a second activity concurrently.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/ExecuteActivityForAdhocSubProcessCmd.java:59

    }

    @Override
    public Execution execute(CommandContext commandContext) {
        ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager(commandContext).findById(executionId);
        if (execution == null) {
            throw new FlowableObjectNotFoundException("No execution found for id '" + executionId + "'", ExecutionEntity.class);
        }

        if (!(execution.getCurrentFlowElement() instanceof AdhocSubProcess adhocSubProcess)) {
            throw new FlowableException("The current flow element of the requested " + execution + " is not an ad-hoc sub process");
        }

        FlowNode foundNode = null;

        // if sequential ordering, only one child execution can be active
        if (adhocSubProcess.hasSequentialOrdering()) {
            if (execution.getExecutions().size() > 0) {
                throw new FlowableException("Sequential ad-hoc sub process in " + execution + " already has an active execution");
            }
        }

        for (FlowElement flowElement : adhocSubProcess.getFlowElements()) {
            if (activityId.equals(flowElement.getId()) && flowElement instanceof FlowNode flowNode) {
                if (flowNode.getIncomingFlows().size() == 0) {
                    foundNode = flowNode;
                }
            }
        }

        if (foundNode == null) {
            throw new FlowableException("The requested activity with id " + activityId + " can not be enabled in " + execution);
        }

        ExecutionEntity activityExecution = CommandContextUtil.getExecutionEntityManager().createChildExecution(execution);
        activityExecution.setCurrentFlowElement(foundNode);
        CommandContextUtil.getAgenda().planContinueProcessOperation(activityExecution);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Wait for the currently active ad-hoc activity to complete before enabling the next one (use a process/task completion listener)
  2. Serialize enablement client-side with a lock/queue or check runtimeService.createExecutionQuery().processInstanceId(pid).active() first
  3. Remove hasSequentialOrdering from the adhocSubProcess in the BPMN if parallel enablement is actually desired

Example fix

// before
managementService.executeCommand(new ExecuteActivityForAdhocSubProcessCmd(execId, nextActivityId));
// after
long active = runtimeService.createExecutionQuery().processInstanceId(pid).count();
if (active == 1) {
    managementService.executeCommand(new ExecuteActivityForAdhocSubProcessCmd(execId, nextActivityId));
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean hasActiveChildren = runtimeService.createExecutionQuery().processInstanceId(pid).count() > 1;
if (hasActiveChildren && adhoc.isSequential()) return;

Type guard

boolean sequentialAdhocBusy(ExecutionEntity adhocExec) { return adhocExec.getExecutions().size() > 0; }

Try / catch

try { ... } catch (FlowableException e) { if (e.getMessage().contains("already has an active execution")) { /* queue the request until current activity completes */ } else throw e; }

Prevention

When it happens

Trigger: Calling the command to enable another ad-hoc activity while a previously enabled activity in the same sequential ad-hoc subprocess is still running (execution.getExecutions().size() > 0).

Common situations: Racing API/service calls that enable ad-hoc activities without waiting for the previous one to finish; UI double-clicks submitting the enable action twice.

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/c4d6057cd719c344. Report an issue: GitHub.