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

Flowable throws this FlowableException when HistoricTaskInstanceQuery.or() is invoked while the query is already inside an active or-block. Nested or-statements are not supported by the query model, so a second or() before endOr() is rejected. It is a query-usage (state) error raised at build time.

Source

Thrown at modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java:2066

        return this;
    }

    @Override
    public HistoricTaskInstanceQuery includeCaseVariables() {
        this.includeCaseVariables = true;
        return this;
    }

    @Override
    public HistoricTaskInstanceQuery includeIdentityLinks() {
        this.includeIdentityLinks = true;
        return this;
    }

    @Override
    public HistoricTaskInstanceQuery or() {
        if (inOrStatement) {
            throw new FlowableException("the query is already in an or statement");
        }

        inOrStatement = true;
        if (databaseType != null) {
            currentOrQueryObject = new HistoricTaskInstanceQueryImpl(commandExecutor, databaseType, taskServiceConfiguration, variableServiceConfiguration);
        } else {
            currentOrQueryObject = new HistoricTaskInstanceQueryImpl(commandExecutor, taskServiceConfiguration, variableServiceConfiguration);
        }
        orQueryObjects.add(currentOrQueryObject);
        return this;
    }

    @Override
    public HistoricTaskInstanceQuery endOr() {
        if (!inOrStatement) {
            throw new FlowableException("endOr() can only be called after calling or()");
        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Call endOr() to close the current or-block before starting a new one with or().
  2. Restructure the query so each or-group is opened and closed exactly once (or() ... endOr()).
  3. Combine the conditions of the second group into the first or-block if they belong together.
  4. Track the inOr state in your builder helper to avoid calling or() twice.

Example fix

// before
query.or().taskName("a").or().taskName("b").endOr(); // throws
// after
query.or().taskName("a").taskName("b").endOr();
Defensive patterns

Strategy: validation

Validate before calling

boolean inOr = ((HistoricTaskInstanceQueryImpl) query).isInOrStatement(); // guard before or()
if (!inOr) { query.or(); }

Try / catch

try {
    query.or();
} catch (FlowableException e) {
    if (e.getMessage().contains("already in an or statement")) {
        throw new IllegalStateException("Query builder misuse: or() called twice before endOr()", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling query.or() ... query.or() without an intervening endOr(), e.g. chaining two or-groups or accidentally calling or() inside an already open or-block.

Common situations: Building queries programmatically where or()/endOr() are called in loops or helper methods that each open their own or-block; copy-pasted query code where an endOr() was deleted.

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