quarkusio/quarkus · error · ErrorDataDecoderException

Error decoding content-transfer-encoding attribute (wrapped

Error message

Error decoding content-transfer-encoding attribute (wrapped NullPointerException/IllegalArgumentException)

What it means

This ErrorDataDecoderException wraps a NullPointerException or IllegalArgumentException thrown while creating the content-transfer-encoding attribute during multipart response parsing. The HttpPostStandardBodyDataFactory (attribute factory) rejected the attribute name or the cleaned header value, so the decoder aborts the whole multipart decode. It indicates a malformed Content-Transfer-Encoding disposition parameter in the multipart response body.

Source

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

                    // read next values and store them in the map as Attribute
                    for (int i = 2; i < contents.length; i++) {
                        String[] values = contents[i].split("=", 2);
                        Attribute attribute;
                        try {
                            attribute = getContentDispositionAttribute(values);
                        } catch (NullPointerException | IllegalArgumentException e) {
                            throw new ErrorDataDecoderException(e);
                        }
                        currentFieldAttributes.put(attribute.getName(), attribute);
                    }
                }
            } else if (HttpHeaderNames.CONTENT_TRANSFER_ENCODING.contentEqualsIgnoreCase(contents[0])) {
                Attribute attribute;
                try {
                    attribute = factory.createAttribute(response, HttpHeaderNames.CONTENT_TRANSFER_ENCODING.toString(),
                            cleanString(contents[1]));
                } catch (NullPointerException | IllegalArgumentException e) {
                    throw new ErrorDataDecoderException(e);
                }

                currentFieldAttributes.put(HttpHeaderNames.CONTENT_TRANSFER_ENCODING, attribute);
            } else if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(contents[0])) {
                Attribute attribute;
                try {
                    attribute = factory.createAttribute(response, HttpHeaderNames.CONTENT_LENGTH.toString(),
                            cleanString(contents[1]));
                } catch (NullPointerException | IllegalArgumentException e) {
                    throw new ErrorDataDecoderException(e);
                }

                currentFieldAttributes.put(HttpHeaderNames.CONTENT_LENGTH, attribute);
            } else if (HttpHeaderNames.CONTENT_TYPE.contentEqualsIgnoreCase(contents[0])) {
                // Take care of possible "multipart/mixed"
                if (HttpHeaderValues.MULTIPART_MIXED.contentEqualsIgnoreCase(contents[1])) {
                    if (currentStatus == MultiPartStatus.DISPOSITION) {
                        String values = StringUtil.substringAfter(contents[2], '=');

View on GitHub (pinned to e1c734241f)

Solutions

  1. Inspect the raw multipart response body (enable wire logging) and fix the malformed Content-Transfer-Encoding parameter on the server.
  2. Check the value after 'Content-Transfer-Encoding=' is non-empty and contains no control characters or stray quotes.
  3. If the server cannot be fixed, sanitize/normalize the response before decoding or use a custom AttributeFactory tolerant of the value.
  4. Compare with a working client (e.g. curl) to confirm the header difference and report/fix the server-side multipart writer.

Example fix

// before (malformed server output)
Content-Disposition: form-data; name="file"; Content-Transfer-Encoding=
// after (well-formed)
Content-Disposition: form-data; name="file"; Content-Transfer-Encoding="binary"
Defensive patterns

Strategy: validation

Validate before calling

// Validate the disposition parameter before the server sends it (server-side check)
String cte = params.get("Content-Transfer-Encoding");
if (cte == null || cte.isBlank()) {
    throw new IllegalStateException("Content-Transfer-Encoding must have a non-empty value");
}

Type guard

static boolean isValidDispositionValue(String v) {
    return v != null && !v.isBlank() && v.chars().allMatch(c -> c >= 0x20 && c != 0x7f);
}

Try / catch

try {
    List<HttpResponsePart> parts = decoder.decode(...);
} catch (ErrorDataDecoderException e) {
    log.warn("Malformed multipart disposition (Content-Transfer-Encoding): {}", e.getMessage(), e);
    throw new BadRequestException("Malformed multipart response", e);
}

Prevention

When it happens

Trigger: The multipart response contains a Content-Transfer-Encoding disposition attribute whose value, after cleanString(), is null or otherwise rejected by factory.createAttribute() (e.g. missing value after '=', empty token, or illegal characters).

Common situations: Non-Quarkus/Netty-incompatible servers or proxies emitting hand-crafted multipart bodies; server frameworks producing 'Content-Transfer-Encoding:' with no value; custom response transformations that mangle disposition headers.

Related errors


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