Activiti/Activiti · error · ActivitiIllegalArgumentException
Cannot combine onlyTimers() with onlyMessages() in the same…
Error message
Cannot combine onlyTimers() with onlyMessages() in the same query
What it means
DeadLetterJobQueryImpl.timers() sets an onlyTimers flag; since timer jobs and message jobs are mutually exclusive filter types, combining it with onlyMessages() is rejected. Activiti validates this eagerly in timers() to prevent contradictory SQL conditions. The same message is thrown from messages() when onlyTimers is already set.
Solutions
- Call only one of timers()/messages() per query instance.
- Model the choice as an enum (TIMER/MESSAGE/ALL) and call the corresponding method at most once.
- Build two separate queries if both types are needed and merge results in application code.
Example fix
// before
DeadLetterJobQuery q = mgmt.createDeadLetterJobQuery().messages();
if (includeTimers) { q.timers(); } // throws
// after
DeadLetterJobQuery q = mgmt.createDeadLetterJobQuery();
if (includeTimers) { q.timers(); } else if (includeMessages) { q.messages(); } Defensive patterns
Strategy: validation
Validate before calling
if (useTimers && useMessages) {
throw new IllegalArgumentException("timers and messages filters are mutually exclusive; pick one or build two queries");
} Type guard
boolean isSingleJobTypeFilter(boolean timers, boolean messages) {
return !(timers && messages);
} Try / catch
try {
DeadLetterJobQuery q = mgmt.createDeadLetterJobQuery().timers();
} catch (ActivitiIllegalArgumentException e) {
LOG.warn("Conflicting job type filters: " + e.getMessage());
} Prevention
- Use an enum (TIMER/MESSAGE/ALL) instead of two independent booleans when mapping UI/config input.
- Do not chain timers()/messages() on the same query instance.
- If both types are needed, run two queries and merge results.
When it happens
Trigger: Chaining .timers() after .messages() (or vice versa) on the same DeadLetterJobQueryImpl instance, e.g. managementService.createDeadLetterJobQuery().messages().timers().
Common situations: Generic 'filter by job type' code that adds both flags from boolean parameters both set to true; copy-pasted query code; UI allowing both checkboxes to be selected and mapping them directly onto the query.
Related errors
- Deployment id is null
- deploymentCategory is null
- deploymentCategoryExclude is null
- deploymentCategoryLike is null
- deploymentKey is null
AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09).
Data as JSON: /api/errors/424645d0f002058c.
Report an issue: GitHub.
Appendix: source
Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/DeadLetterJobQueryImpl.java:103
return this;
}
public DeadLetterJobQueryImpl executionId(String executionId) {
if (executionId == null) {
throw new ActivitiIllegalArgumentException("Provided execution id is null");
}
this.executionId = executionId;
return this;
}
public DeadLetterJobQueryImpl executable() {
executable = true;
return this;
}
public DeadLetterJobQueryImpl timers() {
if (onlyMessages) {
throw new ActivitiIllegalArgumentException(
"Cannot combine onlyTimers() with onlyMessages() in the same query"
);
}
this.onlyTimers = true;
return this;
}
public DeadLetterJobQueryImpl messages() {
if (onlyTimers) {
throw new ActivitiIllegalArgumentException(
"Cannot combine onlyTimers() with onlyMessages() in the same query"
);
}
this.onlyMessages = true;
return this;
}
public DeadLetterJobQueryImpl duedateHigherThan(Date date) {View on GitHub (pinned to 56435b1a97)