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

  1. Send at most one of the two parameters; omit the other entirely.
  2. If neither filter is wanted, send neither parameter (plain /management/dead-letter-jobs returns all).
  3. Fix the client/request builder so flags are mutually exclusive (e.g. if (timersOnly) add timersOnly else if (messagesOnly) add messagesOnly).
  4. 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

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


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)