{"record":{"id":"708042a7398cacd1","repo":"flowable/flowable-engine","slug":"multipart-request-is-required-708042","errorCode":null,"errorMessage":"Multipart request is required","messagePattern":"Multipart request is required","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/DeploymentCollectionResource.java","lineNumber":170,"sourceCode":"                    + \"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.\",\n            code = 201)\n    @ApiResponses(value = {\n            @ApiResponse(code = 201, message = \"Indicates the deployment was created.\"),\n            @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.\")\n    })\n\n    @ApiImplicitParams({\n            @ApiImplicitParam(name = \"file\", dataType = \"file\", paramType = \"form\", required = true)\n    })\n    @PostMapping(value = \"/repository/deployments\", produces = \"application/json\", consumes = \"multipart/form-data\")\n    @ResponseStatus(HttpStatus.CREATED)\n    public DeploymentResponse uploadDeployment(@ApiParam(name = \"deploymentKey\") @RequestParam(value = \"deploymentKey\", required = false) String deploymentKey,\n            @ApiParam(name = \"deploymentName\") @RequestParam(value = \"deploymentName\", required = false) String deploymentName,\n            @ApiParam(name = \"tenantId\") @RequestParam(value = \"tenantId\", required = false) String tenantId,\n            HttpServletRequest request) {\n\n        if (!(request instanceof MultipartHttpServletRequest)) {\n            throw new FlowableIllegalArgumentException(\"Multipart request is required\");\n        }\n        \n        if (restApiInterceptor != null) {\n            restApiInterceptor.executeNewDeploymentForTenantId(tenantId);\n        }\n\n        String queryString = request.getQueryString();\n        Map<String, String> decodedQueryStrings = splitQueryString(queryString);\n\n        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;\n\n        if (multipartRequest.getFileMap().size() == 0) {\n            throw new FlowableIllegalArgumentException(\"Multipart request with file content is required\");\n        }\n\n        MultipartFile file = multipartRequest.getFileMap().values().iterator().next();\n\n        try {","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/repository/DeploymentCollectionResource.java#L152-L188","documentation":"FlowableIllegalArgumentException thrown by uploadDeployment when the HttpServletRequest is not a MultipartHttpServletRequest, i.e. the POST to /repository/deployments did not carry multipart/form-data content. The deployment upload API only accepts multipart requests containing the deployment file.","triggerScenarios":"POST /repository/deployments with Content-Type application/json, application/x-www-form-urlencoded, or omitted Content-Type entirely instead of multipart/form-data with a file part.","commonSituations":"curl calls using -d instead of -F, clients sending the bpmn XML as a raw body or JSON field, missing multipart resolver in Spring config so the request is never wrapped, proxies stripping the Content-Type.","solutions":["Send the request as multipart/form-data, e.g. curl -F \"file=@process.bpmn20.xml\" ...","Set the correct Content-Type header (let the HTTP client set the multipart boundary automatically)","Attach the deployment file as a file part, not as a form field or raw body","Verify the multipart resolver (MultipartResolver / spring.servlet.multipart.enabled=true) is configured server-side"],"exampleFix":"// before\ncurl -u admin:test -X POST -H 'Content-Type: application/json' \\\n  -d '{\"name\":\"myDeployment\"}' http://localhost:8080/flowable-rest/repository/deployments\n// after\ncurl -u admin:test -X POST -F \"deploymentName=myDeployment\" \\\n  -F \"file=@process.bpmn20.xml\" http://localhost:8080/flowable-rest/repository/deployments","handlingStrategy":"validation","validationCode":"// client-side check before sending\nif (!headers['Content-Type'].startsWith('multipart/form-data')) throw new Error('Deployment upload must be multipart/form-data');","typeGuard":null,"tryCatchPattern":"try {\n    rest.postForDeployment(file)\n} catch (HttpClientErrorException.BadRequest e) {\n    if (e.body.message?.contains('Multipart request is required')) {\n        throw new Error('Fix request: use multipart/form-data with a file part, e.g. curl -F file=@process.bpmn20.xml')\n    }\n}","preventionTips":["Always upload deployments with curl -F / FormData, never -d or JSON bodies","Let the HTTP client generate the multipart boundary and Content-Type automatically","Verify server-side multipart resolver is enabled in Spring configuration"],"tags":["multipart","http-request","validation","rest"],"backgroundTag":"invalid-argument-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}