quarkusio/quarkus · error · ErrorDataDecoderException

Error decoding content-length attribute (wrapped NullPointer

Error message

Error decoding content-length attribute (wrapped NullPointerException/IllegalArgumentException)

What it means

This ErrorDataDecoderException wraps a NullPointerException or IllegalArgumentException raised by factory.createAttribute() while decoding the Content-Length disposition attribute of a multipart part. The decoder cannot build a valid attribute from the cleaned header value and fails the entire decode. It signals a malformed or missing Content-Length parameter inside the part's Content-Disposition/header block.

Source

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

                    }
                }
            } 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], '=');
                        multipartMixedBoundary = "--" + values;
                        currentStatus = MultiPartStatus.MIXEDDELIMITER;
                        return decodeMultipart(MultiPartStatus.MIXEDDELIMITER);
                    } else {
                        throw new ErrorDataDecoderException("Mixed Multipart found in a previous Mixed Multipart");
                    }
                } else {
                    for (int i = 1; i < contents.length; i++) {
                        final String charsetHeader = HttpHeaderValues.CHARSET.toString();
                        if (contents[i].regionMatches(true, 0, charsetHeader, 0, charsetHeader.length())) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Capture the response body (logging) and correct the Content-Length parameter emitted by the server, or remove it entirely (it is optional).
  2. Verify no '=' value is missing/empty in the part header line.
  3. Update or fix the server-side multipart serialization library.
  4. As a workaround, route the response through a proxy that normalizes part headers, or decode with a tolerant custom factory.

Example fix

// before (server output)
Content-Disposition: form-data; name="data"; Content-Length=
// after
Content-Disposition: form-data; name="data"; Content-Length="42"
Defensive patterns

Strategy: validation

Validate before calling

// Ensure Content-Length disposition param, if present, is a positive integer
String cl = params.get("Content-Length");
if (cl != null && !cl.chars().allMatch(Character::isDigit)) {
    throw new IllegalStateException("Content-Length disposition param must be numeric, got: " + cl);
}

Type guard

static boolean isValidContentLength(String v) {
    return v == null || (!v.isBlank() && v.chars().allMatch(Character::isDigit));
}

Try / catch

try {
    decoder.decodeMultipart(status);
} catch (ErrorDataDecoderException e) {
    log.error("Failed decoding Content-Length disposition attribute: {}", e.getCause(), e);
    throw new MalformedMultipartException(e);
}

Prevention

When it happens

Trigger: The multipart part carries 'Content-Length=' with an empty or invalid value (e.g. no value after '=', non-numeric or control characters), causing createAttribute to throw NPE/IAE.

Common situations: Hand-rolled or buggy server multipart writers emitting empty Content-Length parameters; proxies that truncate header values; misconfigured gateway mangling part headers.

Related errors


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