flowable/flowable-engine · error · FlowableIllegalArgumentException

Multipart request is required

Error message

Multipart request is required

What it means

FlowableIllegalArgumentException thrown by DeploymentCollectionResource.uploadDeployment when the incoming HttpServletRequest is not a MultipartHttpServletRequest. Deployments are uploaded as file parts, so a plain (non-multipart) POST cannot be processed.

Source

Thrown at modules/flowable-event-registry-rest/src/main/java/org/flowable/eventregistry/rest/service/api/repository/DeploymentCollectionResource.java:168

                    + "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 = "/event-registry-repository/deployments", produces = "application/json", consumes = "multipart/form-data")
    @ResponseStatus(HttpStatus.CREATED)
    public EventDeploymentResponse uploadDeployment(@ApiParam(name = "category") @RequestParam(value = "category", required = false) String category,
            @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

  1. Send the request as multipart/form-data with a file part (curl -F "file=@my-events.json").
  2. Ensure the MultipartResolver is configured in the Spring context so requests are adapted to MultipartHttpServletRequest.
  3. Verify no proxy rewrites or drops the Content-Type header before it reaches the REST app.

Example fix

// before
curl -X POST -H "Content-Type: application/json" -d '{}' http://host/event-registry-repository/deployments
// after
curl -X POST -F "file=@my-events.json" -F "deploymentName=myDeployment" http://host/event-registry-repository/deployments
Defensive patterns

Strategy: validation

Validate before calling

if (!(request instanceof MultipartHttpServletRequest)) throw new IllegalArgumentException("use multipart/form-data with a file part");

Type guard

boolean isMultipart = request instanceof MultipartHttpServletRequest;

Try / catch

try { upload(files); } catch (FlowableIllegalArgumentException e) { return ResponseEntity.badRequest().body("send multipart/form-data"); }

Prevention

When it happens

Trigger: POSTing to the deployments collection endpoint with Content-Type application/json, application/x-www-form-urlencoded, or no body instead of multipart/form-data with a file part.

Common situations: Forgetting to set multipart/form-data in curl/Postman, a reverse proxy or gateway stripping/altering the Content-Type, or the multipart resolver not being configured so Spring never converts the request.

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


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