flowable/flowable-engine · error · FlowableIllegalArgumentException

Multipart request is required

Error message

Multipart request is required

What it means

Thrown by PUT /repository/models/{modelId}/source when the incoming HttpServletRequest is not a MultipartHttpServletRequest. The endpoint consumes multipart/form-data and needs the file part to store as the model's editor source.

Source

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

        return editorSource;
    }

    @ApiOperation(value = "Set the editor source for a model", tags = { "Models" }, consumes = "multipart/form-data",
            notes = "Response body contains the model’s raw editor source. The response’s content-type is set to application/octet-stream, regardless of the content of the source.",
            code = 204)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", dataType = "file", paramType = "form", required = true)
    })
    @ApiResponses(value = {
            @ApiResponse(code = 204, message = "Indicates the model was found and the source has been updated."),
            @ApiResponse(code = 404, message = "Indicates the requested model was not found.")
    })
    @PutMapping(value = "/repository/models/{modelId}/source", consumes = "multipart/form-data")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void setModelSource(@ApiParam(name = "modelId") @PathVariable String modelId, HttpServletRequest request) {
        Model model = getModelFromRequest(modelId);
        if (!(request instanceof MultipartHttpServletRequest)) {
                throw new FlowableIllegalArgumentException("Multipart request is required");
        }

        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 {
            repositoryService.addModelEditorSource(model.getId(), file.getBytes());
        } catch (Exception e) {
            throw new FlowableException("Error adding model editor source extra", e);
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Send the request as multipart/form-data with a file part (curl -X PUT -F 'file=@source.xml' ...)
  2. Do not override Content-Type manually when the client builds the multipart body
  3. Ensure Spring multipart resolution is enabled in the Flowable REST application
  4. Check intermediaries are not stripping multipart headers

Example fix

// before
requests.put(url, data=open('src.xml','rb'), headers={'Content-Type':'application/octet-stream'})
// after
requests.put(url, files={'file': open('src.xml','rb')})
Defensive patterns

Strategy: validation

Validate before calling

if (!"multipart/form-data".equals(request.getContentType().split(";")[0])) throw new IllegalArgumentException("PUT source requires multipart/form-data");

Try / catch

try { setModelSource(modelId, request); } catch (FlowableIllegalArgumentException e) { log.error("resend as multipart/form-data with file part", e); }

Prevention

When it happens

Trigger: PUT /repository/models/{modelId}/source with Content-Type other than multipart/form-data (e.g. application/octet-stream, text/plain); multipart support not configured so Spring never wraps the request.

Common situations: HTTP clients defaulting to raw bodies; missing multipart config in the REST app; gateways rewriting Content-Type and dropping the boundary.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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