{"record":{"id":"149b35c5df447891","repo":"flowable/flowable-engine","slug":"cannot-combine-onlyexternalworkers-with-onlymess-149b35","errorCode":null,"errorMessage":"Cannot combine onlyExternalWorkers() with onlyMessages() in the same query","messagePattern":"Cannot combine onlyExternalWorkers\\(\\) with onlyMessages\\(\\) in the same query","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/SuspendedJobQueryImpl.java","lineNumber":446,"sourceCode":"\n    @Override\n    public SuspendedJobQueryImpl executable() {\n        if (inOrStatement) {\n            this.currentOrQueryObject.executable = true;\n        } else {\n            executable = true;\n        }\n        return this;\n    }\n\n    @Override\n    public SuspendedJobQueryImpl timers() {\n        if (onlyMessages) {\n            throw new FlowableIllegalArgumentException(\"Cannot combine onlyTimers() with onlyMessages() in the same query\");\n        }\n\n        if (onlyExternalWorkers) {\n            throw new FlowableIllegalArgumentException(\"Cannot combine onlyExternalWorkers() with onlyMessages() in the same query\");\n        }\n        if (inOrStatement) {\n            this.currentOrQueryObject.onlyTimers = true;\n        } else {\n            this.onlyTimers = true;\n        }\n        return this;\n    }\n\n    @Override\n    public SuspendedJobQueryImpl messages() {\n        if (onlyTimers) {\n            throw new FlowableIllegalArgumentException(\"Cannot combine onlyTimers() with onlyMessages() in the same query\");\n        }\n\n        if (onlyExternalWorkers) {\n            throw new FlowableIllegalArgumentException(\"Cannot combine onlyExternalWorkers() with onlyMessages() in the same query\");\n        }","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/SuspendedJobQueryImpl.java#L428-L464","documentation":"SuspendedJobQueryImpl.timers() throws FlowableIllegalArgumentException when onlyExternalWorkers was already set. The message reads 'Cannot combine onlyExternalWorkers() with onlyMessages()' (a slightly misleading copy in the source), but the check fires inside timers() when the query is restricted to external-worker jobs. Job-kind filters cannot be combined on a single suspended-job query.","triggerScenarios":"Chaining .externalWorkers().timers() on the same SuspendedJobQueryImpl, including inside or() blocks, to try to fetch both timer and external-worker suspended jobs in one query.","commonSituations":"External-worker (async executor) monitoring code that also wants timer jobs and tries to reuse one query object; migration from older Flowable versions where external-worker filters did not exist and new code combined flags incorrectly.","solutions":["Use either externalWorkers() or timers(), never both, per query.","Issue separate queries for timer jobs and external-worker jobs and union the results.","Reorder or delete the conflicting setter in the chain."],"exampleFix":"// before\nquery.externalWorkers().timers(); // throws in timers()\n// after\nList<Job> jobs = new ArrayList<>();\njobs.addAll(jobService.createSuspendedJobQuery().externalWorkers().list());\njobs.addAll(jobService.createSuspendedJobQuery().timers().list());","handlingStrategy":"try-catch","validationCode":"if (wantTimers && wantExternalWorkers) {\n    throw new IllegalArgumentException(\"Query either timers or externalWorker jobs, not both\");\n}","typeGuard":"boolean safeTimersCall(boolean externalWorkersSet) { return !externalWorkersSet; }","tryCatchPattern":"try {\n    q.externalWorkers().timers();\n} catch (FlowableIllegalArgumentException e) {\n    // run one query per kind and merge\n}","preventionTips":["Model job-kind as a single enum (TIMER|MESSAGE|EXTERNAL_WORKER) in your selection logic so only one can be chosen.","Apply the kind filter last, based on the enum, exactly once.","Note the error text can be misleading; check which setter actually threw."],"tags":["flowable","query","mutually-exclusive","job-service","external-worker"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}