flowable/flowable-engine · error · FlowableIllegalArgumentException

Cannot combine onlyExternalWorkers() with onlyMessages() in

Error message

Cannot combine onlyExternalWorkers() with onlyMessages() in the same query

What it means

Flowable's DeadLetterJobQueryImpl enforces that a dead-letter job query narrows results to at most one job category. Calling timers() after onlyExternalWorkers() and onlyMessages() flags are already set makes the query contradictory, so FlowableIllegalArgumentException is thrown. This fail-fast validation prevents building an impossible SQL filter.

Source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/DeadLetterJobQueryImpl.java:433

    @Override
    public DeadLetterJobQueryImpl executable() {
        if (inOrStatement) {
            this.currentOrQueryObject.executable = true;
        } else {
            this.executable = true;
        }
        return this;
    }

    @Override
    public DeadLetterJobQueryImpl timers() {
        if (onlyMessages) {
            throw new FlowableIllegalArgumentException("Cannot combine onlyTimers() with onlyMessages() in the same query");
        }

        if (onlyExternalWorkers) {
            throw new FlowableIllegalArgumentException("Cannot combine onlyExternalWorkers() with onlyMessages() in the same query");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.onlyTimers = true;
        } else {
            this.onlyTimers = true;
        }
        return this;
    }

    @Override
    public DeadLetterJobQueryImpl messages() {
        if (onlyTimers) {
            throw new FlowableIllegalArgumentException("Cannot combine onlyTimers() with onlyMessages() in the same query");
        }

        if (onlyExternalWorkers) {
            throw new FlowableIllegalArgumentException("Cannot combine onlyExternalWorkers() with onlyMessages() in the same query");
        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Keep at most one of onlyExternalWorkers(), onlyMessages(), timers() in the query chain
  2. Restructure the code so the category filter is chosen once (if/else) instead of chaining conditionally
  3. If a broader query is needed, build a fresh DeadLetterJobQueryImpl instead of reusing a partially configured one

Example fix

// before
managementService.createDeadLetterJobQuery().onlyExternalWorkers().messages().timers();
// after
managementService.createDeadLetterJobQuery().timers(); // pick exactly one category
Defensive patterns

Strategy: validation

Validate before calling

if (useExternalWorkers && useMessages) { throw new IllegalArgumentException("Pick only one of onlyExternalWorkers/messages/timers"); }

Try / catch

try { query = mgmt.createDeadLetterJobQuery().timers(); } catch (FlowableIllegalArgumentException e) { log.error("Conflicting category filters", e); }

Prevention

When it happens

Trigger: Calling deadLetterJobQuery().onlyExternalWorkers() ... .messages() ... .timers() (i.e. timers() invoked while the onlyExternalWorkers flag is set). The check fires in timers() when onlyExternalWorkers is true.

Common situations: Building a query programmatically by appending category filters from user input or configuration without tracking which category flags were already applied; refactoring code that switched from timers/messages filtering to external-worker filtering while leaving stale calls in the chain.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/c9fec14f40fbc9a4. Report an issue: GitHub.