flowable/flowable-engine · error · FlowableIllegalArgumentException

Multipart request with file content is required

Error message

Multipart request with file content is required

What it means

FlowableIllegalArgumentException thrown when the request is multipart (previous check passed) but multipartRequest.getFileMap() is empty — no file part was included. A deployment upload must contain at least one file (.bpmn20.xml/.bpmn/.bar/.zip) to deploy.

Source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/DeploymentCollectionResource.java:183

            @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 {
            DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
            String fileName = file.getOriginalFilename();
            if (StringUtils.isEmpty(fileName) || !(fileName.endsWith(".bpmn20.xml") || fileName.endsWith(".bpmn") || fileName.toLowerCase().endsWith(".bar") || fileName.toLowerCase().endsWith(".zip"))) {

                fileName = file.getName();
            }

            if (fileName.endsWith(".bpmn20.xml") || fileName.endsWith(".bpmn")) {
            	try (final InputStream fileInputStream = file.getInputStream()) {
                    deploymentBuilder.addInputStream(fileName, fileInputStream);
                }
            	
            } else if (fileName.toLowerCase().endsWith(".bar") || fileName.toLowerCase().endsWith(".zip")) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Attach the deployment artifact as a file part, e.g. curl -F "file=@orderProcess.bpmn20.xml"
  2. Ensure the file input is a real MultipartFile part, not a JSON/base64 string field
  3. Check the client sends the part with a standard file content-type so it lands in the multipart file map
  4. Verify the file exists and is non-empty before uploading

Example fix

// before
curl -F "deploymentName=d1" -F "tenantId=t1" http://.../repository/deployments   // no file part
// after
curl -F "deploymentName=d1" -F "file=@orderProcess.bpmn20.xml" http://.../repository/deployments
Defensive patterns

Strategy: validation

Validate before calling

if (!fileField || fileField.size === 0) throw new Error('Deployment upload requires at least one file part');

Type guard

function hasFilePart(form) {
  return Array.from(form.entries()).some(([, v]) => v instanceof File && v.size > 0);
}

Try / catch

try {
    deploy(multipartForm)
} catch (BadRequest e) {
    if (e.message?.includes('Multipart request with file content is required')) {
        throw new Error('Add a file part (e.g. -F "file=@process.bpmn20.xml") to the request');
    }
}

Prevention

When it happens

Trigger: POST /repository/deployments as multipart/form-data containing only string fields (deploymentName, tenantId, deploymentKey) and no file part, or the file field sent under a name the resolver doesn't recognize as a file.

Common situations: See trigger scenarios.

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/c1fd44672af8e87c. Report an issue: GitHub.