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
FlowableException thrown by JobQueryImpl.or() when the query is already inside an or() block. Flowable supports only a single or() segment per query; a second nested or() call has no well-defined semantics, so it is rejected. The fix is to finish the or-block (with endOr()) and start a new query, or merge the conditions inside the existing block.
Source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobQueryImpl.java:563
this.onlyUnlocked = true;
}
return this;
}
@Override
public JobQuery withoutScopeType() {
if (inOrStatement) {
this.currentOrQueryObject.withoutScopeType = true;
} else {
this.withoutScopeType = true;
}
return this;
}
@Override
public JobQuery or() {
if (inOrStatement) {
throw new FlowableException("the query is already in an or statement");
}
inOrStatement = true;
if (commandContext != null) {
currentOrQueryObject = new JobQueryImpl(commandContext, jobServiceConfiguration);
} else {
currentOrQueryObject = new JobQueryImpl(commandExecutor, jobServiceConfiguration);
}
orQueryObjects.add(currentOrQueryObject);
return this;
}
@Override
public JobQuery endOr() {
if (!inOrStatement) {
throw new FlowableException("endOr() can only be called after calling or()");
}
inOrStatement = false;
currentOrQueryObject = null;View on GitHub (pinned to d6d39ce1c6)
Solutions
- Call or() only once per query and place all OR-ed conditions before endOr().
- Ensure every or() is paired with endOr() before any further or() call.
- Refactor filter helpers to detect or-state (or reuse the current or-query object) instead of always calling or().
- If two OR groups are needed, issue two queries and combine results in code.
Example fix
// before
query.or().jobTenantId("t1");
query.or().handlerType("timer"); // throws: already in or statement
// after
query.or()
.jobTenantId("t1")
.handlerType("timer")
.endOr(); Defensive patterns
Strategy: validation
Validate before calling
if (!queryInOrMode) {
query.or();
queryInOrMode = true;
} // always call endOr() before opening another or-block Try / catch
try {
query.or();
} catch (org.flowable.common.engine.api.FlowableException e) {
if (e.getMessage().contains("already in an or statement")) {
query.endOr();
query.or();
} else {
throw e;
}
} Prevention
- Pair every or() with exactly one endOr().
- Design query-builder helpers to append conditions into the existing or-block instead of opening a new one.
- Keep one or-block per query; use multiple queries for multiple OR groups.
When it happens
Trigger: Calling or() twice without an intervening endOr(); building queries recursively where an inner builder also calls or(); adding a shared 'default filter' helper that calls or() onto a query already in or-mode.
Common situations: Composable query-builder frameworks stacking filter fragments each of which opens its own or(); misreading or() as re-entrant like SQL parentheses; tests reusing one query object across multiple filter helpers.
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
- the query is already in an or statement
- endOr() can only be called after calling or()
- The query is already in an or statement
- endOr() can only be called after calling or()
- The query is already in an or statement
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/467bbacb3f9ca07d.
Report an issue: GitHub.