flowable/flowable-engine · error · FlowableIllegalArgumentException

Cannot combine onlyTimers() with onlyExternalWorkers() in th

Error message

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

What it means

DeadLetterJobQueryImpl.externalWorkers() rejects a query that already narrowed to timer jobs. If the onlyTimers flag is set, calling externalWorkers() would combine two exclusive categories, so FlowableIllegalArgumentException is thrown. Timer dead-letter jobs and external-worker dead-letter jobs cannot be selected together this way.

Source

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

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

        if (inOrStatement) {
            this.currentOrQueryObject.onlyMessages = true;
        } else {
            this.onlyMessages = true;
        }
        return this;
    }

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

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

        if (inOrStatement) {
            this.currentOrQueryObject.onlyExternalWorkers = true;
        } else {
            this.onlyExternalWorkers = true;
        }
        return this;
    }


    @Override
    public DeadLetterJobQueryImpl duedateHigherThan(Date date) {
        if (date == null) {
            throw new FlowableIllegalArgumentException("Provided date is null");
        }
        if (inOrStatement) {
            this.currentOrQueryObject.duedateHigherThan = date;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Choose exactly one category filter: timers() or externalWorkers(), not both
  2. Consolidate category selection into a single mutually exclusive decision point
  3. Build a new query object if you need to run separate queries per category

Example fix

// before
mgmt.createDeadLetterJobQuery().timers().externalWorkers();
// after
mgmt.createDeadLetterJobQuery().externalWorkers(); // one category per query
Defensive patterns

Strategy: validation

Validate before calling

if (useTimers && useExternalWorkers) { throw new IllegalArgumentException("timers() and externalWorkers() are mutually exclusive"); }

Try / catch

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

Prevention

When it happens

Trigger: Calling deadLetterJobQuery().timers() ... .externalWorkers(). The check fires in externalWorkers() when onlyTimers is true.

Common situations: Conditionally adding category filters where both timer and external-worker selections are possible; a refactoring that replaced timers() with externalWorkers() but left the original call.

Related errors


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