{"record":{"id":"5de24c8d2a8f4055","repo":"flowable/flowable-engine","slug":"invalid-action-only-move-or-movetohistoryjob-5de24c","errorCode":null,"errorMessage":"Invalid action, only 'move' or 'moveToHistoryJob' is supported.","messagePattern":"Invalid action, only 'move' or 'moveToHistoryJob' is supported\\.","errorType":"http","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobResource.java","lineNumber":301,"sourceCode":"        try {\n            managementService.executeHistoryJob(historyJob.getId());\n        } catch (FlowableObjectNotFoundException e) {\n            // Re-throw to have consistent error-messaging across REST-api\n            throw new FlowableObjectNotFoundException(\"Could not find a job with id '\" + jobId + \"'.\", Job.class);\n        }\n    }\n    \n    @ApiOperation(value = \"Move a single deadletter job. Accepts 'move' and 'moveToHistoryJob' as action.\", tags = { \"Jobs\" }, code = 204)\n    @ApiResponses(value = {\n            @ApiResponse(code = 204, message = \"Indicates the dead letter job was moved. Response-body is intentionally empty.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested job was not found.\"),\n            @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.\")\n    })\n    @PostMapping(\"/cmmn-management/deadletter-jobs/{jobId}\")\n    @ResponseStatus(HttpStatus.NO_CONTENT)\n    public void executeDeadLetterJobAction(@ApiParam(name = \"jobId\") @PathVariable String jobId, @RequestBody RestActionRequest actionRequest) {\n        if (actionRequest == null || !(MOVE_ACTION.equals(actionRequest.getAction()) || MOVE_TO_HISTORY_JOB_ACTION.equals(actionRequest.getAction()))) {\n            throw new FlowableIllegalArgumentException(\"Invalid action, only 'move' or 'moveToHistoryJob' is supported.\");\n        }\n        \n        Job deadLetterJob = getDeadLetterJobById(jobId);\n\n        if (MOVE_ACTION.equals(actionRequest.getAction())) {\n\n            if (restApiInterceptor != null) {\n                restApiInterceptor.moveDeadLetterJob(deadLetterJob, MOVE_ACTION);\n            }\n            /*\n             * Note that the jobType is checked to know which kind of move that needs to be done.\n             * The MOVE_TO_HISTORY_JOB_ACTION allows to specifically force the move to a history job and trigger the else part below.\n             */\n\n            try {\n                if (HistoryJobEntity.HISTORY_JOB_TYPE.equals(deadLetterJob.getJobType())) {\n                    managementService.moveDeadLetterJobToHistoryJob(deadLetterJob.getId(), cmmnEngineConfiguration.getAsyncExecutorNumberOfRetries());\n","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobResource.java#L283-L319","documentation":"Guard in JobResource.executeDeadLetterJobAction: the action field in the request body for moving a dead letter job is something other than the two supported values 'move' and 'moveToHistoryJob', so the endpoint refuses the request.","triggerScenarios":"POST /cmmn-management/deadletter-jobs/{jobId} with null body or an unsupported action such as 'execute' or 'reschedule'.","commonSituations":"Scripts reused from the timer-jobs endpoint (move/reschedule) applied to deadletter jobs, or typos like 'move-to-history-job'.","solutions":["Use action 'move' to retry the job as executable, or 'moveToHistoryJob' to archive it","Match the action strings exactly, camelCase with no separators","Verify the request body is sent as JSON"],"exampleFix":"// before\n{\"action\":\"reschedule\"}\n// after\n{\"action\":\"moveToHistoryJob\"}","handlingStrategy":"validation","validationCode":"const allowed = ['move','moveToHistoryJob'];\nif (!body || !allowed.includes(body.action)) throw new Error(\"deadletter action must be 'move' or 'moveToHistoryJob'\");","typeGuard":"function isValidDeadLetterAction(a) { return a === 'move' || a === 'moveToHistoryJob'; }","tryCatchPattern":"try { await post(`/cmmn-management/deadletter-jobs/${id}`, body); }\ncatch (e) { if (e.status === 400 && /Invalid action/.test(e.message)) { /* fix action to move or moveToHistoryJob */ } else throw e; }","preventionTips":["Map each job endpoint to its exact set of valid actions","Avoid stringly-typed actions in client code — use enums","Re-read Swagger docs when porting scripts between endpoints"],"tags":["rest","validation","bad-request"],"backgroundTag":"invalid-enum-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}