flowable/flowable-engine · error · FlowableException
A request body was expected when updating the task.
Error message
A request body was expected when updating the task.
What it means
Thrown by updateTask when the PUT /runtime/tasks/{taskId} request has no (or a null) JSON body. The handler requires a TaskRequest body even if all fields are optional; a missing body cannot be deserialized to a non-null TaskRequest.
Solutions
- Send a JSON body, e.g. {"name":"new name"} with Content-Type: application/json
- Send {} if you only want to trigger an update without changing fields
- Verify no intermediary (proxy/gateway) strips the request body
Example fix
// before
restTemplate.put(TASK_URL + "/123", null);
// after
restTemplate.exchange(TASK_URL + "/123", HttpMethod.PUT, new HttpEntity<>(mapOf("name", "New name"), jsonHeaders()), Void.class); Defensive patterns
Strategy: validation
Validate before calling
if (!body || typeof body !== 'object' || Object.keys(body).length === 0) body = {}; // always send at least {} Type guard
function isTaskRequest(b) { return b !== null && typeof b === 'object'; } Try / catch
catch (e) { if (e.status === 400 && /request body was expected/.test(e.body && e.body.message)) { /* resend with a JSON body */ } else throw e; } Prevention
- Never send a bodyless PUT; use {} as a minimal payload
- Set Content-Type: application/json on every task update
When it happens
Trigger: PUT /runtime/tasks/{taskId} with no body, empty body, or Content-Type not set to application/json so Spring cannot bind a TaskRequest.
Common situations: Client sends PUT without a JSON payload to 'touch' a task; missing Content-Type header; proxy stripping the body.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- A request body was expected when bulk updating tasks.
- A request body was expected when executing a task action.
- A request body was expected when bulk updating tasks.
- baseUrl can not be null
- Failed to serialize to a RestVariable instance
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/fcffbc3d78171610.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskResource.java:80
@ApiResponse(code = 404, message = "Indicates the requested task was not found.")
})
@GetMapping(value = "/runtime/tasks/{taskId}", produces = "application/json")
public TaskResponse getTask(@ApiParam(name = "taskId") @PathVariable String taskId) {
return restResponseFactory.createTaskResponse(getTaskFromRequest(taskId));
}
@ApiOperation(value = "Update a task", tags = {
"Tasks"}, notes = "All request values are optional. For example, you can only include the assignee attribute in the request body JSON-object, only updating the assignee of the task, leaving all other fields unaffected. When an attribute is explicitly included and is set to null, the task-value will be updated to null. Example: {\"dueDate\" : null} will clear the duedate of the task).")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Indicates the task was updated."),
@ApiResponse(code = 404, message = "Indicates the requested task was not found."),
@ApiResponse(code = 409, message = "Indicates the requested task was updated simultaneously.")
})
@PutMapping(value = "/runtime/tasks/{taskId}", produces = "application/json")
public TaskResponse updateTask(@ApiParam(name = "taskId") @PathVariable String taskId, @RequestBody TaskRequest taskRequest) {
if (taskRequest == null) {
throw new FlowableException("A request body was expected when updating the task.");
}
Task task = getTaskFromRequestWithoutAccessCheck(taskId);
// Populate the task properties based on the request
populateTaskFromRequest(task, taskRequest);
if (restApiInterceptor != null) {
restApiInterceptor.updateTask(task, taskRequest);
}
// Save the task and fetch again, it's possible that an
// assignment-listener has updated
// fields after it was saved so we can not use the in-memory task
taskService.saveTask(task);
task = taskService.createTaskQuery().taskId(task.getId()).singleResult();
return restResponseFactory.createTaskResponse(task);View on GitHub (pinned to d6d39ce1c6)