flowable/flowable-engine · warning · FlowableIllegalArgumentException
Only one of 'timersOnly' or 'messagesOnly' can be provided.
Error message
Only one of 'timersOnly' or 'messagesOnly' can be provided.
What it means
The dead-letter job list endpoint (GET /management/dead-letter-jobs) accepts optional 'timersOnly' and 'messagesOnly' query parameters to narrow the query to timer or message jobs. Supplying both is contradictory, so the controller immediately throws FlowableIllegalArgumentException. It is a pure client-side request-validation error — nothing is executed.
Solutions
- Send at most one of the two parameters; omit the other entirely.
- If neither filter is wanted, send neither parameter (plain /management/dead-letter-jobs returns all).
- Fix the client/request builder so flags are mutually exclusive (e.g. if (timersOnly) add timersOnly else if (messagesOnly) add messagesOnly).
- Remember presence alone triggers the error: don't send empty or false values for both.
Example fix
// before
String url = "/management/dead-letter-jobs?timersOnly=" + timers + "&messagesOnly=" + messages; // both always sent
// after
StringBuilder q = new StringBuilder("/management/dead-letter-jobs");
if (timers) q.append("?timersOnly=true"); else if (messages) q.append("?messagesOnly=true"); Defensive patterns
Strategy: validation
Validate before calling
if (params.containsKey("timersOnly") && params.containsKey("messagesOnly")) {
throw new IllegalArgumentException("Provide at most one of timersOnly/messagesOnly");
} Try / catch
try { jobs = client.getDeadLetterJobs(params); }
catch (FlowableIllegalArgumentException e) { /* strip conflicting params and retry with a single filter */ } Prevention
- Build the query string conditionally so only one flag is ever appended.
- Never send both parameters, even with false/empty values — presence alone is rejected.
- Centralize dead-letter job filtering in one helper that enforces exclusivity.
- Omit both flags when no job-type filter is desired.
When it happens
Trigger: Calling GET /management/dead-letter-jobs with both query params present, e.g. ?timersOnly=true&messagesOnly=true — note the check is on parameter presence (containsKey), so even ?timersOnly=false&messagesOnly=false triggers it.
Common situations: A generic job-filter builder appending both flags unconditionally; a UI sending both toggles; clients modeled after other Flowable endpoints that allow combined filters.
Understand the failure class
Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.
Related errors
- Only one of 'timersOnly' or 'messagesOnly' can be provided.
- A request body was expected when executing the form submit.
- Attachment name is required.
- Error converting request body to RestVariable instance
- Id cannot be null.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/4416d5bda69ff9db.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/DeadLetterJobCollectionResource.java:128
}
if (allRequestParams.containsKey("elementId")) {
query.elementId(allRequestParams.get("elementId"));
}
if (allRequestParams.containsKey("elementName")) {
query.elementName(allRequestParams.get("elementName"));
}
if (allRequestParams.containsKey("handlerType")) {
query.handlerType(allRequestParams.get("handlerType"));
}
if (allRequestParams.containsKey("handlerTypes")) {
query.handlerTypes(Arrays.asList(allRequestParams.get("handlerTypes").split(",")));
}
if (allRequestParams.containsKey("executable")) {
query.executable();
}
if (allRequestParams.containsKey("timersOnly")) {
if (allRequestParams.containsKey("messagesOnly")) {
throw new FlowableIllegalArgumentException("Only one of 'timersOnly' or 'messagesOnly' can be provided.");
}
if (Boolean.parseBoolean(allRequestParams.get("timersOnly"))) {
query.timers();
}
}
if (allRequestParams.containsKey("messagesOnly") && Boolean.parseBoolean(allRequestParams.get("messagesOnly"))) {
query.messages();
}
if (allRequestParams.containsKey("dueBefore")) {
query.duedateLowerThan(RequestUtil.getDate(allRequestParams, "dueBefore"));
}
if (allRequestParams.containsKey("dueAfter")) {
query.duedateHigherThan(RequestUtil.getDate(allRequestParams, "dueAfter"));
}
if (allRequestParams.containsKey("withException") && Boolean.parseBoolean(allRequestParams.get("withException"))) {
query.withException();
}
if (allRequestParams.containsKey("exceptionMessage")) {View on GitHub (pinned to d6d39ce1c6)