flowable/flowable-engine · error · 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 CMMN job query REST endpoint (TimerJobCollectionResource.getJobs) accepts optional 'timersOnly' and 'messagesOnly' query parameters to filter timer vs message jobs. Because the two filters are mutually exclusive (one maps to query.timers(), the other to query.messages()), passing both is ambiguous and the endpoint rejects the request with FlowableIllegalArgumentException before executing the query.

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/TimerJobCollectionResource.java:127

        if (allRequestParams.containsKey("caseDefinitionId")) {
            query.caseDefinitionId(allRequestParams.get("caseDefinitionId"));
        }
        if (allRequestParams.containsKey("scopeDefinitionId")) {
            query.scopeDefinitionId(allRequestParams.get("scopeDefinitionId"));
            query.scopeType(ScopeTypes.CMMN);
        }
        if (allRequestParams.containsKey("elementId")) {
            query.elementId(allRequestParams.get("elementId"));
        }
        if (allRequestParams.containsKey("elementName")) {
            query.elementName(allRequestParams.get("elementName"));
        }
        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)

Solutions

  1. Send only one of 'timersOnly' or 'messagesOnly' in the query string.
  2. If the client needs both timer and message jobs, omit both parameters to get all jobs and filter client-side.
  3. In the client, enforce exclusivity: if both flags are true, clear one before building the request.

Example fix

// before
const params = new URLSearchParams();
if (filters.timersOnly) params.set('timersOnly', 'true');
if (filters.messagesOnly) params.set('messagesOnly', 'true');
// after
const params = new URLSearchParams();
if (filters.timersOnly && !filters.messagesOnly) params.set('timersOnly', 'true');
else if (filters.messagesOnly) params.set('messagesOnly', 'true');
Defensive patterns

Strategy: validation

Validate before calling

function canQueryJobs(filters) {
  const both = filters.timersOnly !== undefined && filters.messagesOnly !== undefined;
  return !both;
}
if (!canQueryJobs(filters)) throw new Error('Send only timersOnly or messagesOnly');

Try / catch

try {
  const jobs = await getJobs(params);
} catch (e) {
  if (e.response?.status === 400 && /timersOnly/.test(e.response.data?.message)) {
    params = pickSingleFilter(params); // resend with one flag
  }
}

Prevention

When it happens

Trigger: GET /cmmn-query/jobs?timersOnly=true&messagesOnly=true — both parameters present as request params, regardless of their boolean values (presence alone triggers the check).

Common situations: A client builds query strings dynamically from a filter object and accidentally includes both flags; a generic job-listing UI exposes both toggles and sends both when both are checked; copy-pasted URLs accumulate stale params.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/f8c016f0e4e5719f. Report an issue: GitHub.