{"record":{"id":"79aed08b056fc3ff","repo":"quarkusio/quarkus","slug":"error-decoding-multipart-content-length-wrapped-i","errorCode":null,"errorMessage":"Error decoding multipart content-length (wrapped IOException)","messagePattern":"Error decoding multipart content-length \\(wrapped IOException\\)","errorType":"exception","errorClass":"ErrorDataDecoderException","httpStatus":null,"severity":"error","filePath":"independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/multipart/QuarkusMultipartResponseDecoder.java","lineNumber":910,"sourceCode":"        }\n        Attribute charsetAttribute = currentFieldAttributes.get(HttpHeaderValues.CHARSET);\n        if (charsetAttribute != null) {\n            try {\n                localCharset = Charset.forName(charsetAttribute.getValue());\n            } catch (IOException | UnsupportedCharsetException e) {\n                throw new ErrorDataDecoderException(e);\n            }\n        }\n        if (currentFileUpload == null) {\n            Attribute filenameAttribute = currentFieldAttributes.get(HttpHeaderValues.FILENAME);\n            Attribute nameAttribute = currentFieldAttributes.get(HttpHeaderValues.NAME);\n            Attribute contentTypeAttribute = currentFieldAttributes.get(HttpHeaderNames.CONTENT_TYPE);\n            Attribute lengthAttribute = currentFieldAttributes.get(HttpHeaderNames.CONTENT_LENGTH);\n            long size;\n            try {\n                size = lengthAttribute != null ? Long.parseLong(lengthAttribute.getValue()) : 0L;\n            } catch (IOException e) {\n                throw new ErrorDataDecoderException(e);\n            } catch (NumberFormatException ignored) {\n                size = 0;\n            }\n            try {\n                String contentType;\n                if (contentTypeAttribute != null) {\n                    contentType = contentTypeAttribute.getValue();\n                } else {\n                    contentType = QuarkusHttpPostBodyUtil.DEFAULT_BINARY_CONTENT_TYPE;\n                }\n                currentFileUpload = factory.createFileUpload(response,\n                        cleanString(nameAttribute.getValue()), cleanString(filenameAttribute.getValue()),\n                        contentType, mechanism.value(), localCharset,\n                        size);\n            } catch (NullPointerException | IOException | IllegalArgumentException e) {\n                throw new ErrorDataDecoderException(e);\n            }\n        }","sourceCodeStart":892,"sourceCodeEnd":928,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/multipart/QuarkusMultipartResponseDecoder.java#L892-L928","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: assuming every part has a readable Content-Length\nlong size = Long.parseLong(lengthAttribute.getValue());\n// after (library-side pattern): tolerate parse issues, surface real IO\ntry {\n    size = lengthAttribute != null ? Long.parseLong(lengthAttribute.getValue()) : 0L;\n} catch (IOException e) {\n    throw new ErrorDataDecoderException(e); // wrap and propagate\n} catch (NumberFormatException ignored) {\n    size = 0L;\n}","handlingStrategy":"retry","validationCode":"// client-side: check content-length headers of multipart parts before parsing\nif (partHeaders.containsKey(\"Content-Length\")) {\n    try { Long.parseLong(partHeaders.getFirst(\"Content-Length\")); }\n    catch (NumberFormatException e) { log.warn(\"Bad Content-Length, ignoring\"); }\n}","typeGuard":null,"tryCatchPattern":"try {\n    multipart = decoder.decodeMultipart(...);\n} catch (ErrorDataDecoderException e) {\n    log.error(\"Multipart decode failed\", e);\n    throw new ClientException(\"Malformed multipart response\", e); // or retry\n}","preventionTips":["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"],"tags":["multipart","netty","io","resteasy-reactive-client"],"backgroundTag":"multipart-decode-failure","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}