{"record":{"id":"06530b127a67fef6","repo":"eclipse-vertx/vert.x","slug":"request-must-have-a-content-type-header-to-decode-06530b","errorCode":null,"errorMessage":"Request must have a content-type header to decode a multipart request","messagePattern":"Request must have a content-type header to decode a multipart request","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"vertx-core/src/main/java/io/vertx/core/http/impl/http1/Http1ServerRequest.java","lineNumber":477,"sourceCode":"          EmptyHttpHeaders.INSTANCE\n        );\n        conn.createWebSocket(this, promise);\n      }\n    });\n    // In case we were paused\n    resume();\n  }\n\n  @Override\n  public HttpServerRequest setExpectMultipart(boolean expect) {\n    synchronized (conn) {\n      checkEnded();\n      expectMultipart = expect;\n      if (expect) {\n        if (decoder == null) {\n          String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE);\n          if (contentType == null) {\n            throw new IllegalStateException(\"Request must have a content-type header to decode a multipart request\");\n          }\n          if (!HttpUtils.isValidMultipartContentType(contentType)) {\n            throw new IllegalStateException(\"Request must have a valid content-type header to decode a multipart request\");\n          }\n          if (!HttpUtils.isValidMultipartMethod(request.method())) {\n            throw new IllegalStateException(\"Request method must be one of POST, PUT, PATCH or DELETE to decode a multipart request\");\n          }\n          NettyFileUploadDataFactory factory = new NettyFileUploadDataFactory(context, this, () -> uploadHandler);\n          factory.setMaxLimit(conn.maxFormAttributeSize());\n          int maxFields = conn.maxFormFields();\n          int maxBufferedBytes = conn.maxFormBufferedBytes();\n          decoder = new HttpPostRequestDecoder(factory, request, HttpConstants.DEFAULT_CHARSET, maxFields, maxBufferedBytes);\n        }\n      } else {\n        decoder = null;\n      }\n      return this;\n    }","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/eclipse-vertx/vert.x/blob/fb308bd8c3f12c79f4ae89bef67fadf6c80d036e/vertx-core/src/main/java/io/vertx/core/http/impl/http1/Http1ServerRequest.java#L459-L495","documentation":"Thrown by Http1ServerRequest.setExpectMultipart(true) when the request has no Content-Type header. Vert.x needs the content type to decide how to decode the body into multipart/form-data parts via HttpPostRequestDecoder; without it, multipart decoding cannot be configured.","triggerScenarios":"Calling request.setExpectMultipart(true) on an incoming HTTP/1.x request whose headers do not include a Content-Type header (e.g. a POST with no Content-Type, or a request built manually by a test client).","commonSituations":"Clients (curl, custom HTTP clients, raw sockets) omitting Content-Type on form uploads; proxies stripping the header; unit tests constructing bare POST requests.","solutions":["Set the Content-Type header on the client request, e.g. 'multipart/form-data; boundary=----boundary'","Check the client actually performs a multipart upload rather than sending a raw body without headers","If the body may lack the header, guard the call: only call setExpectMultipart(true) when request.getHeader(\"Content-Type\") != null"],"exampleFix":"// before\ncurl -X POST http://host/upload --data-binary @file.bin\n// after\ncurl -X POST http://host/upload -H \"Content-Type: multipart/form-data; boundary=XYZ\" -F file=@file.bin","handlingStrategy":"validation","validationCode":"if (request.getHeader(HttpHeaderNames.CONTENT_TYPE) != null) {\n  request.setExpectMultipart(true);\n}","typeGuard":null,"tryCatchPattern":"try { request.setExpectMultipart(true); } catch (IllegalStateException e) { /* no content-type: handle as plain body */ }","preventionTips":["Always send Content-Type on uploads","Set the header before the body is sent","Validate client headers in integration tests"],"tags":["http","multipart","http1","request"],"backgroundTag":"missing-required-argument","analyzedSha":"fb308bd8c3f12c79f4ae89bef67fadf6c80d036e","analyzedAt":"2026-09-06T11:37:12.241Z","contentChangedAt":"2026-09-06T11:37:12.241Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}