flowable/flowable-engine · error · FlowableException
No outgoing sequence flow of element '${flowNode.getId()}' c
Error message
No outgoing sequence flow of element '${flowNode.getId()}' could be selected for continuing the process for ${execution} What it means
After leaving a flow node, TakeOutgoingSequenceFlowsOperation must select outgoing sequence flows. If conditions on existing outgoing flows prevented all of them from being taken, the execution has nowhere to go and the engine throws this FlowableException instead of silently stalling.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/TakeOutgoingSequenceFlowsOperation.java:250
if (outgoingSequenceFlows.size() == 0 && evaluateConditions) { // The elements that set this to false also have no support for default sequence flow
if (defaultSequenceFlowId != null) {
for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
if (defaultSequenceFlowId.equals(sequenceFlow.getId())) {
outgoingSequenceFlows.add(sequenceFlow);
break;
}
}
}
}
// No outgoing found. Ending the execution
if (outgoingSequenceFlows.size() == 0) {
if (flowNode.getOutgoingFlows() == null || flowNode.getOutgoingFlows().size() == 0) {
LOGGER.debug("No outgoing sequence flow found for flow node '{}'.", flowNode.getId());
agenda.planEndExecutionOperation(execution);
} else {
throw new FlowableException("No outgoing sequence flow of element '" + flowNode.getId() + "' could be selected for continuing the process for " + execution);
}
} else {
// Leave, and reuse the incoming sequence flow, make executions for all the others (if applicable)
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
ExecutionEntityManager executionEntityManager = processEngineConfiguration.getExecutionEntityManager();
List<ExecutionEntity> outgoingExecutions = new ArrayList<>(flowNode.getOutgoingFlows().size());
SequenceFlow sequenceFlow = outgoingSequenceFlows.get(0);
// Reuse existing one
execution.setCurrentFlowElement(sequenceFlow);
execution.setActive(false);
outgoingExecutions.add(execution);
// Executions for all the other one
if (outgoingSequenceFlows.size() > 1) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Add a default flow (default attribute) to the node/gateway to catch unmatched cases
- Audit condition expressions and the variable values at runtime (check execution variables)
- Make one condition a catch-all (e.g. true) if a branch must always be taken
- Fix the data/process so a branch condition is always satisfied
Example fix
// before
<exclusiveGateway id="decision" />
<sequenceFlow id="f1" sourceRef="decision" targetRef="big"><conditionExpression>${amount > 100}</conditionExpression></sequenceFlow>
<sequenceFlow id="f2" sourceRef="decision" targetRef="small"><conditionExpression>${amount > 500}</conditionExpression></sequenceFlow>
// after
<exclusiveGateway id="decision" default="f2" />
<sequenceFlow id="f1" sourceRef="decision" targetRef="big"><conditionExpression>${amount > 100}</conditionExpression></sequenceFlow>
<sequenceFlow id="f2" sourceRef="decision" targetRef="small" /> Defensive patterns
Strategy: validation
Validate before calling
// Ensure every exclusive gateway has a default flow before deploying
for (Gateway gw : bpmnModel.getMainProcess().findElementsOfProcess(Gateway.class)) {
if (gw instanceof ExclusiveGateway && ((ExclusiveGateway) gw).getDefaultFlow() == null
&& gw.getOutgoingFlows().stream().allMatch(f -> f.getConditionExpression() != null)) {
throw new IllegalStateException("Gateway " + gw.getId() + " lacks a default flow");
}
} Try / catch
try {
// process advance
} catch (FlowableException e) {
if (e.getMessage().startsWith("No outgoing sequence flow")) {
log.error("Unmatched conditions at node {}; check variables: {}", extractNodeId(e), vars);
}
throw e;
} Prevention
- Add default flows to all exclusive gateways
- Test decision tables/conditions with boundary values
- Log variables at gateways for diagnosis
- Cover all branches in process integration tests
When it happens
Trigger: leaveFlowNode (from handleFlowNode or handleAdhocSubProcess): the node has outgoing flows defined, but every conditional flow evaluated false and there is no default flow, leaving zero selected flows.
Common situations: Exclusive gateways/tasks with conditions like ${amount > 100} that no branch matches; data-driven conditions not satisfied by actual variables; missing default flow.
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
- BPMN XSD could not be found
- The bpmn 2.0 xml is not properly encoded
- Expected an activity behavior in flow node ${flowNode.getId(
- Provided execution id is null
- text is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/ac3c14999a76005e.
Report an issue: GitHub.