{"record":{"id":"1ccb4fe1b9e8bc99","repo":"flowable/flowable-engine","slug":"a-request-body-was-expected-when-executing-a-task","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":500,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskResource.java","lineNumber":113,"sourceCode":"        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\" },\n            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 = \"/cmmn-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":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/task/TaskResource.java#L95-L131","documentation":"POST /cmmn-runtime/tasks/{taskId} executes a task action (claim, complete, delegate, resolve) driven by a TaskActionRequest body. If the body is missing/null, executeTaskAction throws FlowableException because no action can be determined.","triggerScenarios":"POST to /cmmn-runtime/tasks/{taskId} with an empty body or without a JSON body containing the 'action' field.","commonSituations":"Empty POST issued to 'trigger' the task as if it were a signal endpoint; Content-Type not application/json so the body is dropped; copy-paste from endpoints that take no body.","solutions":["Send a body with an action field: {\"action\":\"complete\"} (also claim, delegate, resolve)","Set Content-Type: application/json","Check that the client library/model actually serializes the action request object"],"exampleFix":"// before\nPOST /cmmn-runtime/tasks/123        (empty body)\n// after\nPOST /cmmn-runtime/tasks/123\n{\"action\":\"claim\",\"assignee\":\"john\"}","handlingStrategy":"validation","validationCode":"const ACTIONS = ['claim','complete','delegate','resolve'];\nfunction canExecuteAction(actionRequest) {\n  return actionRequest != null && ACTIONS.includes(actionRequest.action);\n}","typeGuard":"function hasAction(a) {\n  return a != null && typeof a.action === 'string' && a.action.length > 0;\n}","tryCatchPattern":"try {\n  await post(`/cmmn-runtime/tasks/${taskId}`, actionRequest);\n} catch (e) {\n  if (/request body was expected/.test(e.body?.message ?? '')) {\n    throw new Error('task action POST requires a JSON body with an action field');\n  }\n  throw e;\n}","preventionTips":["Never POST to the task action endpoint with an empty body","Set Content-Type: application/json so the body deserializes","Validate the action field client-side before sending"],"tags":["rest-api","request-body","task-action"],"backgroundTag":"empty-request-body","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"}