flowable/flowable-engine · error · FlowableException
Invalid body was supplied
Error message
Invalid body was supplied
What it means
After successfully parsing the request body into a RestVariable, the update-variable endpoint checks that the resulting object is non-null. FlowableException('Invalid body was supplied') is thrown if Jackson parsed the stream but produced a null RestVariable (e.g. body was the literal JSON 'null' or effectively empty). It guards downstream code from dereferencing a null variable.
Solutions
- Send a complete JSON object with at least name, type and value fields.
- Verify client-side serialization is not producing the string 'null'.
- Add a client-side check that the payload object exists before issuing the PUT.
Example fix
// before
curl -X PUT -H 'Content-Type: application/json' .../tasks/123/variables/name -d 'null'
// after
curl -X PUT -H 'Content-Type: application/json' .../tasks/123/variables/name -d '{"name":"name","type":"string","value":"John"}' Defensive patterns
Strategy: type-guard
Validate before calling
if (payload == null || payload.name == null || payload.value === undefined) {
throw new Error('refusing to PUT null/empty variable body');
} Type guard
function isValidBody(v) {
return v != null && typeof v === 'object' && typeof v.name === 'string';
} Try / catch
try {
return await putVariable(url, body);
} catch (e) {
if (String(e.message).includes('Invalid body was supplied')) console.error('body serialized to null:', body);
throw e;
} Prevention
- Check the payload object for null before serializing the request body.
- Never send the literal string 'null' or an empty body to a variable PUT.
- Add a client-side assert that JSON.stringify(payload) !== 'null'.
When it happens
Trigger: PUT /runtime/tasks/{taskId}/variables/{variableName} (non-multipart) with a body that deserializes to null, most commonly the literal body 'null', or an empty/whitespace stream that Jackson maps to null.
Common situations: Client sends 'null' as body; template/serialization bug where variable payload is null; empty body with Content-Type: application/json passing the Jackson parse without exception.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- A request body was expected when executing the form submit.
- taskIds can not be null for bulk update tasks requests
- A request body was expected when bulk updating tasks.
- Attachment name is required.
- Error converting request body to RestVariable instance
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/4893a78c8e297b88.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/task/TaskVariableResource.java:121
if (request instanceof MultipartHttpServletRequest) {
result = setBinaryVariable((MultipartHttpServletRequest) request, task, false);
if (!result.getName().equals(variableName)) {
throw new FlowableIllegalArgumentException("Variable name in the body should be equal to the name used in the requested URL.");
}
} else {
RestVariable restVariable = null;
try {
restVariable = objectMapper.readValue(request.getInputStream(), RestVariable.class);
} catch (Exception e) {
throw new FlowableIllegalArgumentException("Error converting request body to RestVariable instance", e);
}
if (restVariable == null) {
throw new FlowableException("Invalid body was supplied");
}
if (!restVariable.getName().equals(variableName)) {
throw new FlowableIllegalArgumentException("Variable name in the body should be equal to the name used in the requested URL.");
}
result = setSimpleVariable(restVariable, task, false);
}
return result;
}
@ApiOperation(value = "Delete a variable on a task", tags = { "Task Variables" }, nickname = "deleteTaskInstanceVariable", code = 204)
@ApiImplicitParams(@ApiImplicitParam(name = "scope", dataType = "string", value = "Scope of variable to be returned. When local, only task-local variable value is returned. When global, only variable value from the task’s parent execution-hierarchy are returned. When the parameter is omitted, a local variable will be returned if it exists, otherwise a global variable.", paramType = "query"))
@ApiResponses(value = {
@ApiResponse(code = 204, message = "Indicates the task variable was found and has been deleted. Response-body is intentionally empty."),
@ApiResponse(code = 404, message = "Indicates the requested task was not found or the task does not have a variable with the given name. Status message contains additional information about the error.")
})
@DeleteMapping(value = "/runtime/tasks/{taskId}/variables/{variableName}")
@ResponseStatus(HttpStatus.NO_CONTENT)View on GitHub (pinned to d6d39ce1c6)