eclipse-vertx/vert.x · error · IllegalStateException

Request method must be one of POST, PUT, PATCH or DELETE to

Error message

Request method must be one of POST, PUT, PATCH or DELETE to decode a multipart request

What it means

Thrown by Http1ServerRequest.setExpectMultipart(true) when the HTTP method is not one of POST, PUT, PATCH or DELETE (checked by HttpUtils.isValidMultipartMethod). Multipart body decoding is only meaningful for methods that can carry a body.

Source

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

    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
  public synchronized boolean isExpectMultipart() {
    return expectMultipart;
  }

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Ensure the client uses POST/PUT/PATCH/DELETE for the upload
  2. Restrict the route to body-carrying methods, or check request.method() before enabling multipart
  3. Move setExpectMultipart(true) into the POST/PUT handler only

Example fix

// before
request.setExpectMultipart(true);
// after
if (request.method() == HttpMethod.POST || request.method() == HttpMethod.PUT) {
  request.setExpectMultipart(true);
}
Defensive patterns

Strategy: validation

Validate before calling

HttpMethod m = request.method();
if (m == HttpMethod.POST || m == HttpMethod.PUT || m == HttpMethod.PATCH || m == HttpMethod.DELETE) {
  request.setExpectMultipart(true);
}

Try / catch

try { request.setExpectMultipart(true); } catch (IllegalStateException e) { response.setStatusCode(405).end(); }

Prevention

When it happens

Trigger: Calling request.setExpectMultipart(true) inside handlers for GET, HEAD, OPTIONS, TRACE or CONNECT requests, e.g. a shared handler registered on multiple routes including GET.

Common situations: A catch-all route handler that enables multipart regardless of method; routing an upload endpoint with the wrong HTTP method from the client.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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