eclipse-vertx/vert.x · error · IllegalStateException

Request must have a valid content-type header to decode a mu

Error message

Request must have a valid content-type header to decode a multipart request

What it means

Thrown by Http1ServerRequest.setExpectMultipart(true) when the Content-Type header is present but not a valid multipart type (checked by HttpUtils.isValidMultipartContentType, i.e. not multipart/form-data, multipart/mixed etc.). Vert.x only installs a multipart decoder when the content type actually declares multipart.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/http1/Http1ServerRequest.java:480

      }
    });
    // In case we were paused
    resume();
  }

  @Override
  public HttpServerRequest setExpectMultipart(boolean expect) {
    synchronized (conn) {
      checkEnded();
      expectMultipart = expect;
      if (expect) {
        if (decoder == null) {
          String contentType = request.headers().get(HttpHeaderNames.CONTENT_TYPE);
          if (contentType == null) {
            throw new IllegalStateException("Request must have a content-type header to decode a multipart request");
          }
          if (!HttpUtils.isValidMultipartContentType(contentType)) {
            throw new IllegalStateException("Request must have a valid content-type header to decode a multipart request");
          }
          if (!HttpUtils.isValidMultipartMethod(request.method())) {
            throw new IllegalStateException("Request method must be one of POST, PUT, PATCH or DELETE to decode a multipart request");
          }
          NettyFileUploadDataFactory factory = new NettyFileUploadDataFactory(context, this, () -> uploadHandler);
          factory.setMaxLimit(conn.maxFormAttributeSize());
          int maxFields = conn.maxFormFields();
          int maxBufferedBytes = conn.maxFormBufferedBytes();
          decoder = new HttpPostRequestDecoder(factory, request, HttpConstants.DEFAULT_CHARSET, maxFields, maxBufferedBytes);
        }
      } else {
        decoder = null;
      }
      return this;
    }
  }

  @Override

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Set the client Content-Type to multipart/form-data with a boundary parameter
  2. Only call setExpectMultipart(true) when the header starts with 'multipart/'
  3. If the body is urlencoded, do not enable multipart decoding; use request.formAttributes() instead

Example fix

// before
if (request.method() == HttpMethod.POST) { request.setExpectMultipart(true); }
// after
String ct = request.getHeader(HttpHeaderNames.CONTENT_TYPE);
if (ct != null && ct.toLowerCase().startsWith("multipart/")) { request.setExpectMultipart(true); }
Defensive patterns

Strategy: validation

Validate before calling

String ct = request.getHeader(HttpHeaderNames.CONTENT_TYPE);
if (ct != null && ct.toLowerCase().startsWith("multipart/")) {
  request.setExpectMultipart(true);
}

Try / catch

try { request.setExpectMultipart(true); } catch (IllegalStateException e) { logger.warn("Not a multipart request: " + ct); }

Prevention

When it happens

Trigger: Calling request.setExpectMultipart(true) on a request whose Content-Type is e.g. application/x-www-form-urlencoded, application/json, or 'multipart' missing the boundary parameter where required.

Common situations: Server code enabling multipart unconditionally but clients sending urlencoded forms; mismatched client Content-Type; middleware rewriting the header.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of eclipse-vertx/vert.x@fb308bd8c3 (2026-09-06). Data as JSON: /api/errors/fceeaa045c62d059. Report an issue: GitHub.