quarkusio/quarkus · error · ErrorDataDecoderException

Error decoding multipart content-length (wrapped IOException

Error message

Error decoding multipart content-length (wrapped IOException)

What it means

QuarkusMultipartResponseDecoder parses multipart/form-data responses in the REST Easy Reactive client. When a part carries a Content-Length attribute, its value is read from disk (Attribute.getValue() may throw IOException) and parsed as a long. If reading the attribute fails with an IOException, the decoder wraps it in ErrorDataDecoderException, aborting decoding of the whole multipart body. A plain NumberFormatException is tolerated and treated as size 0, so only genuine I/O failures produce this error.

Source

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

        }
        Attribute charsetAttribute = currentFieldAttributes.get(HttpHeaderValues.CHARSET);
        if (charsetAttribute != null) {
            try {
                localCharset = Charset.forName(charsetAttribute.getValue());
            } catch (IOException | UnsupportedCharsetException e) {
                throw new ErrorDataDecoderException(e);
            }
        }
        if (currentFileUpload == null) {
            Attribute filenameAttribute = currentFieldAttributes.get(HttpHeaderValues.FILENAME);
            Attribute nameAttribute = currentFieldAttributes.get(HttpHeaderValues.NAME);
            Attribute contentTypeAttribute = currentFieldAttributes.get(HttpHeaderNames.CONTENT_TYPE);
            Attribute lengthAttribute = currentFieldAttributes.get(HttpHeaderNames.CONTENT_LENGTH);
            long size;
            try {
                size = lengthAttribute != null ? Long.parseLong(lengthAttribute.getValue()) : 0L;
            } catch (IOException e) {
                throw new ErrorDataDecoderException(e);
            } catch (NumberFormatException ignored) {
                size = 0;
            }
            try {
                String contentType;
                if (contentTypeAttribute != null) {
                    contentType = contentTypeAttribute.getValue();
                } else {
                    contentType = QuarkusHttpPostBodyUtil.DEFAULT_BINARY_CONTENT_TYPE;
                }
                currentFileUpload = factory.createFileUpload(response,
                        cleanString(nameAttribute.getValue()), cleanString(filenameAttribute.getValue()),
                        contentType, mechanism.value(), localCharset,
                        size);
            } catch (NullPointerException | IOException | IllegalArgumentException e) {
                throw new ErrorDataDecoderException(e);
            }
        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Inspect the raw multipart response (log or proxy it) for malformed or missing Content-Length headers and fix the server encoder
  2. Ensure the client consumes the response body fully and promptly; avoid buffering huge multipart parts that can trigger attribute eviction — raise io.netty buffer limits or stream the part to disk
  3. Retry the request — transient I/O failures during attribute read often disappear on retry
  4. If the server does not need per-part Content-Length, remove it so the decoder falls back to size 0

Example fix

// before: assuming every part has a readable Content-Length
long size = Long.parseLong(lengthAttribute.getValue());
// after (library-side pattern): tolerate parse issues, surface real IO
try {
    size = lengthAttribute != null ? Long.parseLong(lengthAttribute.getValue()) : 0L;
} catch (IOException e) {
    throw new ErrorDataDecoderException(e); // wrap and propagate
} catch (NumberFormatException ignored) {
    size = 0L;
}
Defensive patterns

Strategy: retry

Validate before calling

// client-side: check content-length headers of multipart parts before parsing
if (partHeaders.containsKey("Content-Length")) {
    try { Long.parseLong(partHeaders.getFirst("Content-Length")); }
    catch (NumberFormatException e) { log.warn("Bad Content-Length, ignoring"); }
}

Try / catch

try {
    multipart = decoder.decodeMultipart(...);
} catch (ErrorDataDecoderException e) {
    log.error("Multipart decode failed", e);
    throw new ClientException("Malformed multipart response", e); // or retry
}

Prevention

When it happens

Trigger: Decoding a multipart response where a part has a Content-Length header/attribute whose backing attribute (e.g. a MemoryAttribute/FileAttribute) cannot be read from its store — typically a corrupted or evicted attribute buffer during HttpPostStandardRequestDecoder-style processing via decodeMultipart -> getFileUpload.

Common situations: Corrupt or truncated multipart responses; server emitting malformed Content-Length attributes; memory pressure causing attribute data loss; custom/buggy multipart encoders on the server side.

Related errors


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