{"record":{"id":"e512e91f8f924856","repo":"flowable/flowable-engine","slug":"only-one-of-timersonly-or-messagesonly-can-be-e512e9","errorCode":null,"errorMessage":"Only one of 'timersOnly' or 'messagesOnly' can be provided.","messagePattern":"Only one of 'timersOnly' or 'messagesOnly' can be provided\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/SuspendedJobCollectionResource.java","lineNumber":129,"sourceCode":"        }\n        if (allRequestParams.containsKey(\"elementId\")) {\n            query.elementId(allRequestParams.get(\"elementId\"));\n        }\n        if (allRequestParams.containsKey(\"elementName\")) {\n            query.elementName(allRequestParams.get(\"elementName\"));\n        }\n        if (allRequestParams.containsKey(\"handlerType\")) {\n            query.handlerType(allRequestParams.get(\"handlerType\"));\n        }\n        if (allRequestParams.containsKey(\"handlerTypes\")) {\n            query.handlerTypes(Arrays.asList(allRequestParams.get(\"handlerTypes\").split(\",\")));\n        }\n        if (allRequestParams.containsKey(\"executable\")) {\n            query.executable();\n        }\n        if (allRequestParams.containsKey(\"timersOnly\")) {\n            if (allRequestParams.containsKey(\"messagesOnly\")) {\n                throw new FlowableIllegalArgumentException(\"Only one of 'timersOnly' or 'messagesOnly' can be provided.\");\n            }\n            if (Boolean.parseBoolean(allRequestParams.get(\"timersOnly\"))) {\n                query.timers();\n            }\n        }\n        if (allRequestParams.containsKey(\"messagesOnly\") && Boolean.parseBoolean(allRequestParams.get(\"messagesOnly\"))) {\n            query.messages();\n        }\n        if (allRequestParams.containsKey(\"dueBefore\")) {\n            query.duedateLowerThan(RequestUtil.getDate(allRequestParams, \"dueBefore\"));\n        }\n        if (allRequestParams.containsKey(\"dueAfter\")) {\n            query.duedateHigherThan(RequestUtil.getDate(allRequestParams, \"dueAfter\"));\n        }\n        if (allRequestParams.containsKey(\"withException\") && Boolean.parseBoolean(allRequestParams.get(\"withException\"))) {\n            query.withException();\n        }\n        if (allRequestParams.containsKey(\"withRetriesLeft\") && Boolean.parseBoolean(allRequestParams.get(\"withRetriesLeft\"))) {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/SuspendedJobCollectionResource.java#L111-L147","documentation":"SuspendedJobCollectionResource.getJobs validates query parameters for listing suspended jobs. Because timersOnly and messagesOnly are mutually exclusive filters, providing both request parameters raises FlowableIllegalArgumentException with this message. The API deliberately rejects the ambiguous combination instead of merging filters.","triggerScenarios":"GET /management/suspended-jobs?timersOnly=true&messagesOnly=true (both parameters present in the request, regardless of value, since the check is containsKey on either parameter name).","commonSituations":"Client builds query string by appending all configured filters without removing the other; a UI that lets users tick both 'timers only' and 'messages only'; copied cURL commands with leftover parameters.","solutions":["Send only one of timersOnly or messagesOnly in the request","If you want both timers and messages, omit both parameters (default returns all suspended jobs)","Fix the client-side query builder to make the two options mutually exclusive in the UI/logic","Filter client-side if you truly need both sets in one call: fetch all and filter by job type"],"exampleFix":"// before\nGET /management/suspended-jobs?timersOnly=true&messagesOnly=true\n// after\nGET /management/suspended-jobs?timersOnly=true","handlingStrategy":"validation","validationCode":"function buildSuspendedJobsQuery(params) {\n  if (params.timersOnly !== undefined && params.messagesOnly !== undefined) {\n    throw new Error(\"Only one of 'timersOnly' or 'messagesOnly' can be provided.\");\n  }\n  return new URLSearchParams(Object.entries(params)).toString();\n}","typeGuard":null,"tryCatchPattern":"try {\n  return fetchSuspendedJobs(params);\n} catch (e) {\n  if (String(e.message).includes(\"timersOnly\")) {\n    return fetchSuspendedJobs({ ...params, messagesOnly: undefined });\n  }\n  throw e;\n}","preventionTips":["In UIs, make 'timers only' and 'messages only' a mutually exclusive radio group, not independent checkboxes","Strip the opposite parameter in query-builder helpers when one is set","Remember the check is on parameter presence (containsKey), so even timersOnly=false with messagesOnly present throws"],"tags":["rest-api","flowable","query-parameters","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T16:30:33.424Z"}