flowable/flowable-engine · error · FlowableIllegalArgumentException
Multipart request is required
Error message
Multipart request is required
What it means
The CMMN REST deployment upload endpoint only accepts multipart/form-data requests because the deployment artifact (a .cmmn/.bar/.zip file) must be transmitted as a file part. The controller checks `request instanceof MultipartHttpServletRequest` and throws FlowableIllegalArgumentException when a plain (non-multipart) request is received.
Source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/repository/DeploymentCollectionResource.java:169
+ "An additional parameter (form-field) can be passed in the request body with name tenantId. The value of this field will be used as the id of the tenant this deployment is done in.",
code = 201)
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Indicates the deployment was created."),
@ApiResponse(code = 400, message = "Indicates there was no content present in the request body or the content mime-type is not supported for deployment. The status-description contains additional information.")
})
@ApiImplicitParams({
@ApiImplicitParam(name = "file", dataType = "file", paramType = "form", required = true)
})
@PostMapping(value = "/cmmn-repository/deployments", produces = "application/json", consumes = "multipart/form-data")
@ResponseStatus(HttpStatus.CREATED)
public CmmnDeploymentResponse uploadDeployment(@ApiParam(name = "deploymentKey") @RequestParam(value = "deploymentKey", required = false) String deploymentKey,
@ApiParam(name = "deploymentName") @RequestParam(value = "deploymentName", required = false) String deploymentName,
@ApiParam(name = "tenantId") @RequestParam(value = "tenantId", required = false) String tenantId,
HttpServletRequest request) {
if (!(request instanceof MultipartHttpServletRequest)) {
throw new FlowableIllegalArgumentException("Multipart request is required");
}
if (restApiInterceptor != null) {
restApiInterceptor.executeNewDeploymentForTenantId(tenantId);
}
String queryString = request.getQueryString();
Map<String, String> decodedQueryStrings = splitQueryString(queryString);
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
if (multipartRequest.getFileMap().size() == 0) {
throw new FlowableIllegalArgumentException("Multipart request with file content is required");
}
MultipartFile file = multipartRequest.getFileMap().values().iterator().next();
try {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Send the request as multipart/form-data with the deployment file as a file part, e.g. `curl -F "file=@myCase.cmmn.xml" .../repository/deployments`.
- Ensure the client sets Content-Type: multipart/form-data (let the HTTP library generate the boundary rather than setting it manually).
- On the server, verify a MultipartResolver (e.g. StandardServletMultipartResolver) is configured and the servlet supports multipart (enable multipart in web.xml or via MultipartConfigElement).
- Check intermediate proxies/API gateways preserve the multipart Content-Type and body.
Example fix
// before
curl -X POST -H 'Content-Type: application/json' -d '{}' http://host/flowable-rest/cmmn-query/repository/deployments
// after
curl -X POST -F 'file=@case.cmmn.xml' http://host/flowable-rest/cmmn-query/repository/deployments Defensive patterns
Strategy: validation
Validate before calling
if (!contentType || !contentType.startsWith('multipart/form-data')) {
throw new Error('Deployment upload requires multipart/form-data');
} Prevention
- Always use the HTTP client's file-upload helper (curl -F, requests files=, FormData).
- Never set the multipart boundary manually; let the library generate Content-Type.
- Confirm the server has multipart parsing enabled before deploying via REST in a new environment.
When it happens
Trigger: POST to /cmmn-query/repository/deployments (DeploymentCollectionResource.uploadDeployment) with Content-Type other than multipart/form-data, e.g. application/x-www-form-urlencoded or application/json, or a multipart request that failed to be parsed so Spring did not wrap it as MultipartHttpServletRequest.
Common situations: Clients using curl without -F, HTTP clients posting JSON bodies, a missing MultipartResolver/failed multipart parsing configuration, or proxies/gateways that strip or rewrite the Content-Type header.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Multipart request with file content is required
- Value of type ${value.getClass()} is not supported as multi
- Variable name in the body should be equal to the name used i
- Could not find a case instance with id '${caseInstanceId}'.
- Historic task instance '' variable value for couldn't be fo
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b9b482e2399a3cdd.
Report an issue: GitHub.