{"record":{"id":"e2cbb545bb7e3a66","repo":"flowable/flowable-engine","slug":"cannot-combine-onlytimers-with-onlymessages-in","errorCode":null,"errorMessage":"Cannot combine onlyTimers() with onlyMessages() in the same query","messagePattern":"Cannot combine onlyTimers\\(\\) 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/DeadLetterJobQueryImpl.java","lineNumber":429,"sourceCode":"            this.handlerTypes = handlerTypes;\n        }\n        return this;\n    }\n\n    @Override\n    public DeadLetterJobQueryImpl executable() {\n        if (inOrStatement) {\n            this.currentOrQueryObject.executable = true;\n        } else {\n            this.executable = true;\n        }\n        return this;\n    }\n\n    @Override\n    public DeadLetterJobQueryImpl 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 DeadLetterJobQueryImpl messages() {\n        if (onlyTimers) {\n            throw new FlowableIllegalArgumentException(\"Cannot combine onlyTimers() with onlyMessages() in the same query\");\n        }","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/DeadLetterJobQueryImpl.java#L411-L447","documentation":"DeadLetterJobQueryImpl.timers() throws FlowableIllegalArgumentException when onlyMessages is already set on the query. onlyTimers(), onlyMessages(), and onlyExternalWorkers() are mutually exclusive job-type filters; combining them would produce contradictory criteria, so the second call fails fast. The message text mentions onlyMessages because that flag was set first.","triggerScenarios":"Calling deadLetterJobQuery().onlyMessages()...timers() (or vice versa) on the same query object; also triggers when onlyExternalWorkers was set and timers() is called (with its own companion message). Reusing a cached/shared query instance that already carries one of these flags.","commonSituations":"Building query filters dynamically from user-selected checkboxes that allow multiple type selections; appending filters to a shared query template; merging two queries' criteria into one object.","solutions":["Pick exactly one job-type filter per query: only onlyTimers(), onlyMessages(), or onlyExternalWorkers().","If multiple types are needed, run separate queries and merge the results in application code.","Always start from a fresh managementService.createDeadLetterJobQuery() instead of reusing a configured query object."],"exampleFix":"// before\nDeadLetterJobQuery q = mgmt.createDeadLetterJobQuery().onlyMessages();\nif (includeTimers) { q.timers(); } // throws\n// after\nDeadLetterJobQuery q = mgmt.createDeadLetterJobQuery();\nif (includeTimers) {\n    q = mgmt.createDeadLetterJobQuery().timers();\n} else {\n    q = mgmt.createDeadLetterJobQuery().onlyMessages();\n}","handlingStrategy":"validation","validationCode":"int typeFilters = (useTimers ? 1 : 0) + (useMessages ? 1 : 0) + (useExternalWorkers ? 1 : 0);\nif (typeFilters > 1) { throw new IllegalArgumentException(\"Select at most one of timers/messages/externalWorkers\"); }","typeGuard":"boolean canApplyTypeFilter(DeadLetterJobQueryImpl q) { return !q.onlyMessages && !q.onlyExternalWorkers; }","tryCatchPattern":"try { query.timers(); } catch (FlowableIllegalArgumentException e) { log.warn(\"Conflicting job type filters: {}\", e.getMessage()); query = managementService.createDeadLetterJobQuery(); }","preventionTips":["Never reuse a query instance across different filter configurations","Translate multi-select UI options into separate queries merged in code","Centralize dead-letter query construction in one helper that enforces a single type filter"],"tags":["flowable","query","mutually-exclusive","validation"],"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-14T11:17:12.474Z"}