{"record":{"id":"e2d26fce9cae7605","repo":"flowable/flowable-engine","slug":"a-request-body-was-expected-when-executing-a-task-e2d26f","errorCode":null,"errorMessage":"A request body was expected when executing a task action.","messagePattern":"A request body was expected when executing a task action\\.","errorType":"http","errorClass":"FlowableException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskResource.java","lineNumber":112,"sourceCode":"        // fields after it was saved so we can not use the in-memory task\n        taskService.saveTask(task);\n        task = taskService.createTaskQuery().taskId(task.getId()).singleResult();\n\n        return restResponseFactory.createTaskResponse(task);\n    }\n\n    @ApiOperation(value = \"Tasks actions\", tags = {\"Tasks\"}, notes = \"\")\n    @ApiResponses(value = {\n            @ApiResponse(code = 200, message = \"Indicates the action was executed.\"),\n            @ApiResponse(code = 400, message = \"When the body contains an invalid value or when the assignee is missing when the action requires it.\"),\n            @ApiResponse(code = 404, message = \"Indicates the requested task was not found.\"),\n            @ApiResponse(code = 409, message = \"Indicates the action cannot be performed due to a conflict. Either the task was updates simultaneously or the task was claimed by another user, in case of the claim action.\")\n    })\n    @PostMapping(value = \"/runtime/tasks/{taskId}\")\n    @ResponseStatus(value = HttpStatus.OK)\n    public void executeTaskAction(@ApiParam(name = \"taskId\") @PathVariable String taskId, @RequestBody TaskActionRequest actionRequest) {\n        if (actionRequest == null) {\n            throw new FlowableException(\"A request body was expected when executing a task action.\");\n        }\n\n        Task task = getTaskFromRequestWithoutAccessCheck(taskId);\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.executeTaskAction(task, actionRequest);\n        }\n\n        if (TaskActionRequest.ACTION_COMPLETE.equals(actionRequest.getAction())) {\n            completeTask(task, actionRequest);\n\n        } else if (TaskActionRequest.ACTION_CLAIM.equals(actionRequest.getAction())) {\n            claimTask(task, actionRequest);\n\n        } else if (TaskActionRequest.ACTION_UNCLAIM.equals(actionRequest.getAction())) {\n            unclaimTask(task);\n\n        } else if (TaskActionRequest.ACTION_DELEGATE.equals(actionRequest.getAction())) {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskResource.java#L94-L130","documentation":"Thrown by executeTaskAction when POST /runtime/tasks/{taskId} is called without a JSON body. The TaskActionRequest (containing the 'action' field) is mandatory, so a null body makes the action indeterminable.","triggerScenarios":"POST /runtime/tasks/{taskId} with empty body or without Content-Type: application/json; client forgets the {\"action\":\"complete\"} payload.","commonSituations":"Calling the action endpoint to 'ping' the task; curl POST without -d; HTTP client defaults dropping the body on POST.","solutions":["Send a body like {\"action\":\"complete\"} with Content-Type: application/json","Use a supported action: complete, claim, delegate, resolve","Ensure the HTTP client serializes and sends the request entity"],"exampleFix":"// before\ncurl -X POST .../runtime/tasks/123\n// after\ncurl -X POST -H 'Content-Type: application/json' -d '{\"action\":\"complete\"}' .../runtime/tasks/123","handlingStrategy":"validation","validationCode":"if (!body || !body.action) throw new Error('actionRequest with an action field is required');","typeGuard":"function isTaskActionRequest(b) { return b !== null && typeof b === 'object' && typeof b.action === 'string'; }","tryCatchPattern":"catch (e) { if (e.status === 400 && /request body was expected/.test(e.body && e.body.message)) { /* resend with {action: ...} */ } else throw e; }","preventionTips":["Always include {\"action\":\"...\"} in the POST body","Set Content-Type: application/json so Spring binds the body","Check HTTP client config doesn't drop entities on POST"],"tags":["rest","http","request-body","task-action"],"backgroundTag":"missing-required-argument","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"}