{"record":{"id":"986e41eb0cba6bcb","repo":"quarkusio/quarkus","slug":"missing-boundary-parameter-in-content-type","errorCode":null,"errorMessage":"Missing boundary parameter in Content-Type","messagePattern":"Missing boundary parameter in Content-Type","errorType":"http","errorClass":"WebApplicationException","httpStatus":500,"severity":"error","filePath":"independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/EntityPartReader.java","lineNumber":55,"sourceCode":"        }\n        if (mediaType == null || !mediaType.getType().equals(\"multipart\")) {\n            return false;\n        }\n        if (genericType instanceof ParameterizedType pt) {\n            Type[] args = pt.getActualTypeArguments();\n            return args.length == 1 && args[0] == EntityPart.class;\n        }\n        return false;\n    }\n\n    @Override\n    public List<EntityPart> readFrom(Class<List<EntityPart>> type, Type genericType,\n            Annotation[] annotations, MediaType mediaType,\n            MultivaluedMap<String, String> httpHeaders, InputStream entityStream)\n            throws IOException, WebApplicationException {\n        String boundary = mediaType.getParameters().get(\"boundary\");\n        if (boundary == null) {\n            throw new WebApplicationException(\"Missing boundary parameter in Content-Type\");\n        }\n        byte[] body = entityStream.readAllBytes();\n\n        List<EntityPart> parts = new ArrayList<>();\n        EntityPartCollector collector = new EntityPartCollector(parts);\n        MultipartParser.ParseState parser = MultipartParser.beginParse(\n                collector, boundary.getBytes(StandardCharsets.US_ASCII), \"UTF-8\");\n        parser.parse(ByteBuffer.wrap(body));\n        return parts;\n    }\n\n    private static class EntityPartCollector implements MultipartParser.PartHandler {\n        private final List<EntityPart> parts;\n        private CaseInsensitiveMap<String> currentHeaders;\n        private ByteArrayOutputStream currentData;\n\n        EntityPartCollector(List<EntityPart> parts) {\n            this.parts = parts;","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/providers/serialisers/EntityPartReader.java#L37-L73","documentation":"EntityPartReader.readFrom throws a WebApplicationException when the multipart/form-data Content-Type header has no boundary parameter. RFC 2046 requires a boundary delimiter to delimit multipart parts, so the multipart parser cannot even start without it.","triggerScenarios":"Sending a request with Content-Type multipart/form-data but omitting the boundary parameter, e.g. manually setting the Content-Type header instead of letting the client generate it, or a server reading a List<EntityPart> from a request whose header lacks boundary.","commonSituations":"Hand-constructed multipart requests; proxies/gateways stripping Content-Type parameters; clients that set the header before the body is assembled so no boundary exists yet.","solutions":["Let the REST client set the multipart Content-Type itself instead of setting it manually","If setting manually, include the same boundary used in the body: multipart/form-data; boundary=...","Fix proxies/load balancers that rewrite or strip the boundary parameter","Generate the boundary first, build the body with it, then set the header"],"exampleFix":"// before\nRequest req = target.request().header(\"Content-Type\", \"multipart/form-data\");\n// after (let the framework build it, or supply a boundary)\nString boundary = \"----quarkusBoundary\";\nRequest req = target.request()\n    .header(\"Content-Type\", \"multipart/form-data; boundary=\" + boundary);","handlingStrategy":"validation","validationCode":"String contentType = headers.getFirst(\"Content-Type\");\nif (contentType == null || !contentType.contains(\"boundary=\")) {\n    throw new IllegalStateException(\"multipart Content-Type must include a boundary parameter\");\n}","typeGuard":"boolean hasMultipartBoundary(MediaType mediaType) {\n    return mediaType != null && mediaType.getParameters().get(\"boundary\") != null;\n}","tryCatchPattern":"try {\n    List<EntityPart> parts = request.readEntity(new GenericType<List<EntityPart>>() {});\n} catch (WebApplicationException e) {\n    // respond 400: client sent multipart without boundary\n    return Response.status(400, \"Missing boundary parameter\").build();\n}","preventionTips":["Never hard-set multipart Content-Type headers manually; let the client framework generate them","If manual, generate the boundary first and reuse it in body and header","Verify proxies/gateways preserve Content-Type parameters","Test multipart uploads end-to-end with real clients"],"tags":["resteasy-reactive","multipart","content-type","boundary","web-application-exception"],"backgroundTag":"missing-multipart-boundary","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}