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
- Inspect the raw multipart response (log or proxy it) for malformed or missing Content-Length headers and fix the server encoder
- 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
- Retry the request — transient I/O failures during attribute read often disappear on retry
- 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
- Validate server-side multipart encoding with integration tests
- Stream large multipart bodies instead of buffering in memory
- Retry transient decode failures
- Keep Netty/RESTEasy Reactive client versions aligned
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
- Unsupported multipart message element type. Expected FileAtt
- Unsupported multipart response element type: " + httpData.ge
- setting content of MultiByteHttpData is not supported
- adding content to MultiByteHttpData is not supported
- getting all the contents of a MultiByteHttpData is not suppo
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/79aed08b056fc3ff.
Report an issue: GitHub.