flowable/flowable-engine · error · FlowableIllegalArgumentException
Invalid action, only 'move' or 'reschedule' are supported.
Error message
Invalid action, only 'move' or 'reschedule' are supported.
What it means
The CMMN REST API timer-job action endpoint only supports the 'move' and 'reschedule' actions. Flowable throws FlowableIllegalArgumentException when the request body is missing or its 'action' field is anything else. It is a client-side request validation error, not an engine failure.
Solutions
- Set the request body's action field to exactly 'move' or 'reschedule'
- Ensure the JSON body is actually sent and deserialized (Content-Type: application/json, non-null body)
- Check API docs / Swagger for the endpoint's accepted actions before calling
Example fix
// before
curl -X POST /cmmn-management/timer-jobs/42 -d '{"action":"execute"}'
// after
curl -X POST /cmmn-management/timer-jobs/42 -d '{"action":"reschedule","dueDate":"2026-01-01T10:00:00Z"}' Defensive patterns
Strategy: validation
Validate before calling
const allowed = ['move','reschedule'];
if (!body || !allowed.includes(body.action)) throw new Error("action must be 'move' or 'reschedule'"); Type guard
function isValidTimerAction(a) { return a === 'move' || a === 'reschedule'; } Try / catch
try { await post(`/cmmn-management/timer-jobs/${id}`, body); }
catch (e) { if (e.status === 400 && /Invalid action/.test(e.message)) { /* fix action field */ } else throw e; } Prevention
- Keep a constants map of valid actions per endpoint
- Always send an explicit JSON body with Content-Type: application/json
- Consult the endpoint's Swagger definition before scripting
When it happens
Trigger: POST /cmmn-management/timer-jobs/{jobId} with a null/empty body, or with an action value other than exactly 'move' or 'reschedule' (e.g. 'execute', 'Move', 'retry').
Common situations: Copy-pasting request payloads from the BPMN REST API or deadletter-job endpoint (which use different action names), case mismatches, or omitting the JSON body entirely.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Either channelDefinitionId or channelDefinitionKey is…
- Either eventDefinitionId or eventDefinitionKey is required.
- Invalid action, only 'move' or 'moveToHistoryJob' is…
- Variable operation is missing for variable:
- Variable value is missing for variable:
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/5987db0908624c5d.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobResource.java:243
try {
managementService.executeJob(job.getId());
} catch (FlowableObjectNotFoundException e) {
// Re-throw to have consistent error-messaging across REST-api
throw new FlowableObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
}
}
@ApiOperation(value = "Execute a single job action (move or reschedule)", tags = { "Jobs" }, code = 204)
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Indicates the timer job action was executed. Response-body is intentionally empty."),
@ApiResponse(code = 404, message = "Indicates the requested job was not found."),
@ApiResponse(code = 500, message = "Indicates the an exception occurred while executing the job. The status-description contains additional detail about the error. The full error-stacktrace can be fetched later on if needed.")
})
@PostMapping("/cmmn-management/timer-jobs/{jobId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void executeTimerJobAction(@ApiParam(name = "jobId") @PathVariable String jobId, @RequestBody TimerJobActionRequest actionRequest) {
if (actionRequest == null || !(MOVE_ACTION.equals(actionRequest.getAction()) || RESCHEDULE_ACTION.equals(actionRequest.getAction()))) {
throw new FlowableIllegalArgumentException("Invalid action, only 'move' or 'reschedule' are supported.");
}
Job job = getTimerJobById(jobId);
if (MOVE_ACTION.equals(actionRequest.getAction())) {
try {
managementService.moveTimerToExecutableJob(job.getId());
} catch (FlowableObjectNotFoundException e) {
// Re-throw to have consistent error-messaging across REST-api
throw new FlowableObjectNotFoundException("Could not find a timer job with id '" + jobId + "'.", Job.class);
}
} else if (RESCHEDULE_ACTION.equals(actionRequest.getAction())) {
if (actionRequest.getDueDate() == null) {
throw new FlowableIllegalArgumentException("Invalid reschedule timer action. Reschedule timer actions must have a valid due date");
}
try {
managementService.rescheduleTimeDateValueJob(job.getId(), actionRequest.getDueDate());
} catch (FlowableObjectNotFoundException e) {View on GitHub (pinned to d6d39ce1c6)