flowable/flowable-engine · error · FlowableException

Invalid body was supplied

Error message

Invalid body was supplied

What it means

Thrown by updateVariable when the body deserializes successfully but yields a null RestVariable — in practice this means an empty or effectively empty request body was supplied. Flowable raises FlowableException 'Invalid body was supplied' because a variable update requires an actual variable representation.

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/CaseInstanceVariableResource.java:112

        RestVariable result = null;
        if (request instanceof MultipartHttpServletRequest) {
            result = setBinaryVariable((MultipartHttpServletRequest) request, caseInstance.getId(), CmmnRestResponseFactory.VARIABLE_CASE, false,
                    false, RestVariable.RestVariableScope.GLOBAL, createVariableInterceptor(caseInstance));

            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, caseInstance.getId(), false, false, RestVariable.RestVariableScope.GLOBAL, CmmnRestResponseFactory.VARIABLE_CASE, createVariableInterceptor(caseInstance));
        }
        return result;
    }
    
    @ApiOperation(value = "Update a single variable on a case instance asynchronously", tags = { "Case Instance Variables" }, nickname = "updateCaseInstanceVariableAsync",
            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 global variables can be set in a case instance.\n"
                    + "NB: Swagger V2 specification doesn't 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.cmmn.service.api.engine.variable.RestVariable", value = "Create a variable on a case instance", paramType = "body", example = "{\n" +
                    "    \"name\":\"intProcVar\"\n" +
                    "    \"type\":\"integer\"\n" +

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Provide a non-empty RestVariable JSON body with at least name, value and type.
  2. Check the client so it doesn't serialize undefined/null as the whole body.
  3. Verify HTTP client configuration that the body is actually attached and Content-Length > 0.
  4. If you intended to delete the variable, use the DELETE variable endpoint instead of PUT.

Example fix

// before
curl -X PUT .../variables/count -H 'Content-Type: application/json'
// after
curl -X PUT .../variables/count -H 'Content-Type: application/json' -d '{"name":"count","value":0,"type":"integer"}'
Defensive patterns

Strategy: validation

Validate before calling

if (!body || Object.keys(body).length === 0) {
  throw new Error('updateVariable requires a non-empty RestVariable body');
}

Type guard

function hasRestVariableBody(v) {
  return v !== null && v !== undefined && typeof v === 'object';
}

Try / catch

try {
  await updateCaseVariable(caseId, name, body);
} catch (e) {
  if (e.status === 400 || e.status === 500) { /* check that a body was actually attached */ }
  else throw e;
}

Prevention

When it happens

Trigger: PUT /cmmn-runtime/case-instances/{id}/variables/{name} with a completely empty body (or a body Jackson maps to null, e.g. the literal 'null') on a non-multipart request.

Common situations: Calling the endpoint with no body at all (curl without -d); clients serializing undefined/null variables; middleware stripping the body; tests sending empty payloads expecting defaults.

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/412e8b8643aa1706. Report an issue: GitHub.