flowable/flowable-engine · error · FlowableIllegalArgumentException

Multipart request with file content is required

Error message

Multipart request with file content is required

What it means

Thrown by AppDeploymentCollectionResource.uploadDeployment when the request is multipart but contains no file entries (multipartRequest.getFileMap().size() == 0). Flowable needs at least one file part to build the deployment. It signals a structurally valid multipart request with missing file content.

Source

Thrown at modules/flowable-app-engine-rest/src/main/java/org/flowable/app/rest/service/api/repository/AppDeploymentCollectionResource.java:165

    @PostMapping(value = "/app-repository/deployments", produces = "application/json", consumes = "multipart/form-data")
    @ResponseStatus(HttpStatus.CREATED)
    public AppDeploymentResponse uploadDeployment(@ApiParam(name = "tenantId") @RequestParam(value = "tenantId", required = false) String tenantId, HttpServletRequest request) {

        if (restApiInterceptor != null) {
            restApiInterceptor.executeNewDeploymentForTenantId(tenantId);
        }
        
        if (!(request instanceof MultipartHttpServletRequest)) {
            throw new FlowableIllegalArgumentException("Multipart request is required");
        }
        
        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 {
            AppDeploymentBuilder deploymentBuilder = appRepositoryService.createDeployment();
            String fileName = file.getOriginalFilename();
            if (StringUtils.isEmpty(fileName) || !(fileName.endsWith(".app") || fileName.toLowerCase().endsWith(".bar") || fileName.toLowerCase().endsWith(".zip"))) {
                fileName = file.getName();
            }

            if (fileName.endsWith(".app")) {
                try (final InputStream fileInputStream = file.getInputStream()) {
                    deploymentBuilder.addInputStream(fileName, fileInputStream);
                }

            } else if (fileName.toLowerCase().endsWith(".bar") || fileName.toLowerCase().endsWith(".zip")) {
                try (InputStream fileInputStream = file.getInputStream();

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Attach at least one file part, e.g. FormData.append('file', fileObject) in JS or curl -F 'file=@my.app'.
  2. Use a proper file input (<input type='file'>) so the part is a file, not a text field.
  3. Verify the part is non-empty and has a filename.
  4. Log multipartRequest.getFileMap() server-side to confirm which parts Spring sees.

Example fix

// before
const fd = new FormData(); fd.append('deploymentName', 'x'); // no file part
// after
const fd = new FormData();
fd.append('file', appFileInput.files[0]);
fd.append('deploymentName', 'x');
Defensive patterns

Strategy: validation

Validate before calling

// client-side: ensure a file part is appended
if (!fileInput.files || fileInput.files.length === 0) {
  throw new Error('Select an .app or .zip file before uploading');
}
const fd = new FormData();
fd.append('file', fileInput.files[0]);

Try / catch

try {
    restTemplate.postForEntity(uploadUrl, requestEntity, String.class);
} catch (HttpClientErrorException.BadRequest e) {
    if (e.getResponseBodyAsString().contains("file content is required")) {
        // retry with an actual file part in the multipart body
    }
}

Prevention

When it happens

Trigger: POST /app-repository/deployments with multipart/form-data but only text/field parts, or an empty file part not registered in the file map.

Common situations: Client sends form fields (deploymentName etc.) but forgets the file input; wrong part name/type so Spring does not classify it as a file; browser form without enctype='multipart/form-data'; empty FormData append.

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