flowable/flowable-engine · error · FlowableException
the query is already in an or statement
Error message
the query is already in an or statement
What it means
ExecutionQueryImpl.or() opens an OR block in the query but cannot be nested; calling or() while already inside an or statement throws FlowableException. Flowable query API supports only one flat or() ... endOr() block per query.
Source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/ExecutionQueryImpl.java:980
@Override
public ExecutionQuery startedBy(String userId) {
if (userId == null) {
throw new FlowableIllegalArgumentException("user id is null");
}
if (inOrStatement) {
currentOrQueryObject.startedBy = userId;
} else {
this.startedBy = userId;
}
return this;
}
@Override
public ExecutionQuery or() {
if (inOrStatement) {
throw new FlowableException("the query is already in an or statement");
}
inOrStatement = true;
if (commandContext != null) {
currentOrQueryObject = new ExecutionQueryImpl(commandContext, processEngineConfiguration);
} else {
currentOrQueryObject = new ExecutionQueryImpl(commandExecutor, processEngineConfiguration);
}
orQueryObjects.add(currentOrQueryObject);
return this;
}
@Override
public ExecutionQuery endOr() {
if (!inOrStatement) {
throw new FlowableException("endOr() can only be called after calling or()");
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Call or() once, then chain multiple conditions inside the block, and close with endOr()
- Track an inOr flag in your builder so or() is only emitted when not already inside an OR block
- Refactor conditions that require nested ORs into two separate queries and merge/union the results in application code
Example fix
// before
query.or().processDefinitionKey("k1").or().processDefinitionKey("k2").endOr();
// after
query.or().processDefinitionKey("k1").processDefinitionKey("k2").endOr(); Defensive patterns
Strategy: validation
Validate before calling
if (!builder.isInsideOrBlock()) {
builder.openOr();
} Try / catch
try {
query.or();
} catch (FlowableException e) {
if (!e.getMessage().contains("already in an or statement")) throw e;
// continue adding conditions inside the existing OR block
} Prevention
- Call or() exactly once per query, then chain all OR conditions before endOr()
- Never emit or() inside loops of optional criteria
- Encapsulate OR building in a helper that tracks open/close state
When it happens
Trigger: Calling query.or() twice without an intervening endOr(), e.g. building criteria in a loop that adds or() per condition, or concatenating two query-builder fragments that each start with or().
Common situations: Dynamic query builders that append or() unconditionally for each optional filter; reusable filter helper methods that each call or() internally.
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
- endOr() can only be called after calling or()
- the query is already in an or statement
- Deployment id is null
- Deployment ids is null
- deploymentName is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b7b609cd0571fbe1.
Report an issue: GitHub.