flowable/flowable-engine · error · FlowableException
Invalid body was supplied
Error message
Invalid body was supplied
What it means
Flowable's REST endpoint for updating a process-instance variable requires a JSON body deserializable into a RestVariable object. After parsing, if the deserialized object is null (i.e. an empty body or a JSON literal 'null'), the endpoint throws FlowableException("Invalid body was supplied"). This guards downstream logic that expects a non-null variable payload.
Solutions
- Send a valid JSON RestVariable body, e.g. {"name":"<variableName>","type":"string","value":"myValue"}.
- Ensure the variable name in the body matches the {variableName} URL segment.
- Verify the client sets Content-Type: application/json and actually transmits the body (check curl -v output or proxy logs).
- If using a reverse proxy, confirm it does not drop request bodies on PUT.
Example fix
// before
curl -X PUT -H 'Content-Type: application/json' \
http://host/flowable-rest/runtime/process-instances/123/variables/orderId
// after
curl -X PUT -H 'Content-Type: application/json' \
-d '{"name":"orderId","type":"string","value":"ABC-1"}' \
http://host/flowable-rest/runtime/process-instances/123/variables/orderId Defensive patterns
Strategy: validation
Validate before calling
const body = { name: variableName, type: 'string', value: 'x' };
if (!body || !body.name) throw new Error('RestVariable body required');
await fetch(url, { method: 'PUT', headers: {'Content-Type':'application/json'}, body: JSON.stringify(body) }); Type guard
function isValidRestVariable(v) {
return v != null && typeof v.name === 'string' && v.name.length > 0 && 'value' in v;
} Try / catch
try {
const res = await api.put(`/process-instances/${id}/variables/${name}`, body);
} catch (e) {
if (e.response && /Invalid body was supplied/.test(e.response.data && e.response.data.message || '')) {
// rebuild and retry with a proper RestVariable body
}
} Prevention
- Never send a PUT without a JSON body to variable endpoints.
- Build the body from the same variable name used in the URL.
- Log request bodies in integration tests to catch empty payloads early.
When it happens
Trigger: PUT/POST to /runtime/process-instances/{processInstanceId}/variables/{variableName} with an empty request body, a body of literal 'null', or a body whose content is dropped before it reaches objectMapper.readValue(request.getInputStream(), RestVariable.class).
Common situations: Clients sending PUT without a body (e.g. curl -X PUT without -d), proxies/gateways stripping bodies, Content-Type header set but payload omitted, or test scripts calling the endpoint with no data.
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
- AttachmentRequest properties not found in request
- A request body was expected when bulk updating tasks.
- A request body was expected when executing the form submit.
- Attachment name is required.
- Batch part with id ' ' does not have a batch part document.
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/4df63bba69212602.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ProcessInstanceVariableResource.java:117
RestVariable result = null;
if (request instanceof MultipartHttpServletRequest) {
result = setBinaryVariable((MultipartHttpServletRequest) request, execution, false, 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("request body could not be transformed to a 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, execution, false, false);
}
return result;
}
@ApiOperation(value = "Update a single variable on a process instance asynchronously", tags = { "Process Instance Variables" }, nickname = "updateProcessInstanceVariableAsync",
notes = "This endpoint can be used in 2 ways: By passing a JSON Body (RestVariable) or by passing a multipart/form-data Object.\n"
+ "Note that scope is ignored, only local variables can be set in a process instance.\n"
+ "NB: Swagger V2 specification does not support this use case that is why this endpoint might be buggy/incomplete if used with other tools.")
@ApiImplicitParams({
@ApiImplicitParam(name = "body", type = "org.flowable.rest.service.api.engine.variable.RestVariable", value = "Create a variable on a process instance", paramType = "body", example = "{\n" +
" \"name\":\"intProcVar\"\n" +
" \"type\":\"integer\"\n" +View on GitHub (pinned to d6d39ce1c6)