quarkusio/quarkus · error · ErrorDataDecoderException

Needs a boundary value

Error message

Needs a boundary value

What it means

QuarkusHttpPostBodyUtil.getMultipartDataBoundary parses the multipart Content-Type header to extract the boundary parameter. When the header contains a 'boundary=' token but the substring after '=' is null or absent, it throws HttpPostRequestDecoder.ErrorDataDecoderException with this message. The client cannot frame multipart body parts without a boundary string, so decoding fails fast.

Source

Thrown at independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/multipart/QuarkusHttpPostBodyUtil.java:300

        // Check if Post using "multipart/form-data; boundary=--89421926422648 [; charset=xxx]"
        String[] headerContentType = splitHeaderContentType(contentType);
        final String multiPartHeader = HttpHeaderValues.MULTIPART_FORM_DATA.toString();
        if (headerContentType[0].regionMatches(true, 0, multiPartHeader, 0, multiPartHeader.length())) {
            int mrank;
            int crank;
            final String boundaryHeader = HttpHeaderValues.BOUNDARY.toString();
            if (headerContentType[1].regionMatches(true, 0, boundaryHeader, 0, boundaryHeader.length())) {
                mrank = 1;
                crank = 2;
            } else if (headerContentType[2].regionMatches(true, 0, boundaryHeader, 0, boundaryHeader.length())) {
                mrank = 2;
                crank = 1;
            } else {
                return null;
            }
            String boundary = StringUtil.substringAfter(headerContentType[mrank], '=');
            if (boundary == null) {
                throw new HttpPostRequestDecoder.ErrorDataDecoderException("Needs a boundary value");
            }
            if (boundary.charAt(0) == '"') {
                String bound = boundary.trim();
                int index = bound.length() - 1;
                if (bound.charAt(index) == '"') {
                    boundary = bound.substring(1, index);
                }
            }
            final String charsetHeader = HttpHeaderValues.CHARSET.toString();
            if (headerContentType[crank].regionMatches(true, 0, charsetHeader, 0, charsetHeader.length())) {
                String charset = StringUtil.substringAfter(headerContentType[crank], '=');
                if (charset != null) {
                    return new String[] { "--" + boundary, charset };
                }
            }
            return new String[] { "--" + boundary };
        }
        return null;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Do not set the multipart Content-Type header manually; let the REST Client set it including a generated boundary
  2. If setting it manually, include a non-empty value: Content-Type: multipart/form-data; boundary=<token>
  3. Inspect the outgoing Content-Type header for a truncated boundary value (e.g. missing text after '=')
  4. Ensure no middleware/proxy rewrites or truncates the Content-Type header

Example fix

// before
request.header("Content-Type", "multipart/form-data; boundary");
// after
// remove the manual header; the multipart encoder sets it:
// Content-Type: multipart/form-data; boundary=XXXX
Defensive patterns

Strategy: validation

Validate before calling

String ct = requestContentType; // e.g. header value
if (ct != null && ct.toLowerCase().startsWith("multipart/")) {
    int i = ct.indexOf("boundary=");
    if (i < 0 || ct.substring(i + "boundary=".length()).isBlank()) {
        throw new IllegalStateException("multipart Content-Type must include a boundary value");
    }
}

Try / catch

try {
    return client.multipartCall(...);
} catch (jakarta.ws.rs.ProcessingException e) {
    if (e.getCause() instanceof HttpPostRequestDecoder.ErrorDataDecoderException) {
        throw new IllegalStateException("Fix the multipart Content-Type: boundary value missing", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Sending a multipart request whose Content-Type header declares a boundary attribute incorrectly, e.g. 'multipart/form-data' with no '=' after boundary, or a manually set header like 'Content-Type: multipart/form-data; boundary' (missing value).

Common situations: Manually constructing the multipart Content-Type header instead of letting the client generate it; copying a header from a tool (curl, Postman) and dropping the boundary value; proxy layers that strip header values.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/694cab1482a90ad9. Report an issue: GitHub.