flowable/flowable-engine · error · FlowableIllegalArgumentException
Invalid action, only 'move' or 'moveToHistoryJob' is support
Error message
Invalid action, only 'move' or 'moveToHistoryJob' is supported.
What it means
executeDeadLetterJobAction performs bulk actions on dead letter jobs (POST /cmmn-management/deadletter-jobs). Only 'move' (back to jobs) and 'moveToHistoryJob' actions are allowed; any other or missing action string throws FlowableIllegalArgumentException.
Source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobCollectionResource.java:200
}
if (restApiInterceptor != null) {
restApiInterceptor.accessJobInfoWithQuery(query);
}
return paginateList(allRequestParams, query, "id", JobQueryProperties.PROPERTIES, restResponseFactory::createJobResponseList);
}
@ApiOperation(value = "Move a bulk of deadletter jobs. Accepts 'move' and 'moveToHistoryJob' as action.", tags = { "Jobs" }, code = 204)
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Indicates the dead letter jobs where moved. Response-body is intentionally empty."),
@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.")
})
@ResponseStatus(value = HttpStatus.NO_CONTENT)
@PostMapping("/cmmn-management/deadletter-jobs")
public void executeDeadLetterJobAction(@RequestBody BulkMoveDeadLetterActionRequest actionRequest) {
if (actionRequest == null || !(MOVE_ACTION.equals(actionRequest.getAction()) || MOVE_TO_HISTORY_JOB_ACTION.equals(actionRequest.getAction()))) {
throw new FlowableIllegalArgumentException("Invalid action, only 'move' or 'moveToHistoryJob' is supported.");
}
Collection<String> jobIds = actionRequest.getJobIds();
long existingJobIdCount = managementService.createDeadLetterJobQuery().jobIds(jobIds).count();
if (jobIds.size() != existingJobIdCount) {
List<Job> foundJobs = managementService.createDeadLetterJobQuery().jobIds(jobIds).list();
for (Job job : foundJobs) {
jobIds.remove(job.getId());
}
throw new FlowableObjectNotFoundException(
"Could not find a dead letter job(s) with id(s) {" + jobIds.stream().collect(Collectors.joining(",")) + "}", Job.class);
}
if (MOVE_ACTION.equals(actionRequest.getAction())) {
if (restApiInterceptor != null) {
restApiInterceptor.bulkMoveDeadLetterJobs(actionRequest.getJobIds(), MOVE_ACTION);
}
managementService.bulkMoveDeadLetterJobs(actionRequest.getJobIds(), cmmnEngineConfiguration.getAsyncExecutorNumberOfRetries());
} else if (MOVE_TO_HISTORY_JOB_ACTION.equals(actionRequest.getAction())) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Set action to exactly 'move' or 'moveToHistoryJob' in the request body.
- Ensure the JSON body matches BulkMoveDeadLetterActionRequest with a non-null action and jobIds list.
- For other job handling (delete/retry), use the engine ManagementService API or a different endpoint.
Example fix
// before
{"action":"retry","jobIds":["42"]}
// after
{"action":"move","jobIds":["42"]} Defensive patterns
Strategy: validation
Validate before calling
const VALID_ACTIONS=["move","moveToHistoryJob"]; if (!VALID_ACTIONS.includes(actionRequest.action)) throw new Error(`action must be 'move' or 'moveToHistoryJob'`);
Prevention
- Copy action strings from the API docs/tests exactly (case-sensitive).
- Always send a non-null action field with jobIds.
- Use SDK constants for action names.
When it happens
Trigger: POST /cmmn-management/deadletter-jobs with a body whose action is 'retry', 'delete', 'MOVE', empty, or absent — anything not exactly 'move' or 'moveToHistoryJob'.
Common situations: Clients assuming a 'retry' action exists (older Flowable versions used different semantics); case-sensitive mismatch ('Move'); missing action field after a request-body refactor.
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
- Only one of 'timersOnly' or 'messagesOnly' can be provided.
- Variable operation is missing for variable: ${variable.getNa
- Variable value is missing for variable: ${variable.getName()
- Value-only query (without a variable-name) is only supported
- Only string variable values are supported when ignoring casi
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/22e7aab5f95a1fb5.
Report an issue: GitHub.