flowable/flowable-engine · error · FlowableIllegalArgumentException
Cannot combine onlyTimers() with onlyMessages() in the same
Error message
Cannot combine onlyTimers() with onlyMessages() in the same query
What it means
FlowableIllegalArgumentException thrown by JobQueryImpl.timers() when onlyMessages is already set on the query. The onlyTimers and onlyMessages filters are mutually exclusive: a job is either a timer job or a message/async job, so combining both would yield a logically empty query. Flowable rejects the combination at query-build time.
Source
Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobQueryImpl.java:412
}
@Override
public JobQuery handlerTypes(Collection<String> handlerTypes) {
if (handlerTypes == null) {
throw new FlowableIllegalArgumentException("Provided handlerTypes are null");
}
if (inOrStatement) {
this.currentOrQueryObject.handlerTypes = handlerTypes;
} else {
this.handlerTypes = handlerTypes;
}
return this;
}
@Override
public JobQuery timers() {
if (onlyMessages) {
throw new FlowableIllegalArgumentException("Cannot combine onlyTimers() with onlyMessages() in the same query");
}
if (inOrStatement) {
this.currentOrQueryObject.onlyTimers = true;
} else {
this.onlyTimers = true;
}
return this;
}
@Override
public JobQuery messages() {
if (onlyTimers) {
throw new FlowableIllegalArgumentException("Cannot combine onlyTimers() with onlyMessages() in the same query");
}
if (inOrStatement) {
this.currentOrQueryObject.onlyMessages = true;
} else {
this.onlyMessages = true;View on GitHub (pinned to d6d39ce1c6)
Solutions
- Call only one of timers() or messages() per query; drop the conflicting call.
- Track which filter was set and use onlyMessages()/onlyTimers() mutually exclusively in your builder.
- If both job kinds are needed, run two separate queries and merge results instead of one query with both flags.
- To remove a previously set filter, build a fresh JobQueryImpl rather than flipping flags.
Example fix
// before
if (filterTimers) query.timers();
if (filterMessages) query.messages(); // throws when both true
// after
if (filterTimers && filterMessages) {
// run two queries, or treat as 'no filter'
} else if (filterTimers) {
query.timers();
} else if (filterMessages) {
query.messages();
} Defensive patterns
Strategy: validation
Validate before calling
if (filterTimers && filterMessages) {
throw new IllegalArgumentException("timers and messages filters are mutually exclusive; run separate queries");
} Try / catch
try {
query.timers();
} catch (org.flowable.common.engine.api.FlowableIllegalArgumentException e) {
// onlyMessages already set: rebuild the query with only one kind filter
query = jobService.createJobQuery();
} Prevention
- Model timers/messages as a single enum choice (TIMERS | MESSAGES | ALL) instead of two booleans.
- Track which kind-filter was applied on the query instance.
- Write unit tests for your query builder covering both-flags-selected input.
When it happens
Trigger: Calling jobQuery.timers() after jobQuery.messages() on the same query instance, or building a query with conditionally-added filters where both flags end up set (also applies inside an or() block).
Common situations: Dynamic query builders that add filters based on user-selected checkboxes where 'timers' and 'messages' were both selected; copy-pasted query code accumulating both flags.
Related errors
- Cannot combine onlyTimers() with onlyMessages() in the same
- appsDefinitionIds is null
- Empty appsDefinitionIds
- category is null
- query is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/939861b5b2cf7a0b.
Report an issue: GitHub.