eclipse-vertx/vert.x · error · IllegalStateException

Sending form requires multipart/form-data or " + HttpHeaders

Error message

Sending form requires multipart/form-data or " + HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED + " content type instead of " + contentType

What it means

Vert.x throws this IllegalStateException when send() is called with a form body but the Content-Type header is neither multipart/form-data nor application/x-www-form-urlencoded. The client needs to know which form encoding to use and cannot serialize the form otherwise.

Source

Thrown at vertx-core/src/main/java/io/vertx/core/http/impl/HttpClientRequestImpl.java:315

    HttpPostRequestEncoder.EncoderMode encoderMode = multipartMixed ? HttpPostRequestEncoder.EncoderMode.RFC1738 : HttpPostRequestEncoder.EncoderMode.HTML5;
    ClientMultipartFormUpload form;
    try {
      boolean multipart;
      if (contentType == null) {
        multipart = impl.isMultipart();
        contentType = multipart ? HttpHeaders.MULTIPART_FORM_DATA.toString() : HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED.toString();
        putHeader(HttpHeaderNames.CONTENT_TYPE, contentType);
      } else {
        if (contentType.equalsIgnoreCase(HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED.toString())) {
          if (impl.isMultipart()) {
            throw new IllegalStateException("Multipart form requires multipart/form-data content type instead of "
              + HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED);
          }
          multipart = false;
        } else if (contentType.equalsIgnoreCase(HttpHeaders.MULTIPART_FORM_DATA.toString())) {
          multipart = true;
        } else {
          throw new IllegalStateException("Sending form requires multipart/form-data or "
            + HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED + " content type instead of " + contentType);
        }
      }
      form = new ClientMultipartFormUpload(context, impl, multipart, encoderMode);
    } catch (Exception e) {
      reset(0, e);
      return response();
    }
    for (Map.Entry<String, String> header : form.headers()) {
      if (header.getKey().equalsIgnoreCase(CONTENT_LENGTH.toString())) {
        if (Integer.parseInt(header.getValue()) < 0) {
          // Bug ?
          continue;
        }
      }
      putHeader(header.getKey(), header.getValue());
    }
    return send(form);

View on GitHub (pinned to fb308bd8c3)

Solutions

  1. Remove the custom Content-Type header so Vert.x chooses the correct form encoding automatically
  2. Set Content-Type to multipart/form-data or application/x-www-form-urlencoded explicitly
  3. If you need a JSON body, replace the form with a JSON-serialized buffer instead of setting a form

Example fix

// before
request.putHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setForm(form);
// after
request.setForm(form); // content type set automatically, or:
request.putHeader(HttpHeaders.CONTENT_TYPE, HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED);
Defensive patterns

Strategy: validation

Validate before calling

String ct = request.headers().get(HttpHeaders.CONTENT_TYPE);
if (ct != null && !HttpHeaders.MULTIPART_FORM_DATA.contentEqualsIgnoreCase(ct)
    && !HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED.contentEqualsIgnoreCase(ct)) {
  request.headers().remove(HttpHeaders.CONTENT_TYPE);
}

Try / catch

try {
  request.send();
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Sending form requires")) {
    request.headers().remove(HttpHeaders.CONTENT_TYPE);
    request.send();
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling send() on a request with a form or multipart form set while the Content-Type header was overwritten with some other value, e.g. application/json, text/plain, or a vendor content type.

Common situations: Global header interceptors setting Content-Type: application/json on every request including form submissions; copy-pasted code that sets a content type incompatible with the form; manual header construction typos.

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/4123ab82f38102a7. Report an issue: GitHub.