{"record":{"id":"77140b63ae47b43f","repo":"quarkusio/quarkus","slug":"mixed-multipart-found-in-a-previous-mixed-multipar","errorCode":null,"errorMessage":"Mixed Multipart found in a previous Mixed Multipart","messagePattern":"Mixed Multipart found in a previous Mixed Multipart","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":774,"sourceCode":"                Attribute attribute;\n                try {\n                    attribute = factory.createAttribute(response, HttpHeaderNames.CONTENT_LENGTH.toString(),\n                            cleanString(contents[1]));\n                } catch (NullPointerException | IllegalArgumentException e) {\n                    throw new ErrorDataDecoderException(e);\n                }\n\n                currentFieldAttributes.put(HttpHeaderNames.CONTENT_LENGTH, attribute);\n            } else if (HttpHeaderNames.CONTENT_TYPE.contentEqualsIgnoreCase(contents[0])) {\n                // Take care of possible \"multipart/mixed\"\n                if (HttpHeaderValues.MULTIPART_MIXED.contentEqualsIgnoreCase(contents[1])) {\n                    if (currentStatus == MultiPartStatus.DISPOSITION) {\n                        String values = StringUtil.substringAfter(contents[2], '=');\n                        multipartMixedBoundary = \"--\" + values;\n                        currentStatus = MultiPartStatus.MIXEDDELIMITER;\n                        return decodeMultipart(MultiPartStatus.MIXEDDELIMITER);\n                    } else {\n                        throw new ErrorDataDecoderException(\"Mixed Multipart found in a previous Mixed Multipart\");\n                    }\n                } else {\n                    for (int i = 1; i < contents.length; i++) {\n                        final String charsetHeader = HttpHeaderValues.CHARSET.toString();\n                        if (contents[i].regionMatches(true, 0, charsetHeader, 0, charsetHeader.length())) {\n                            String values = StringUtil.substringAfter(contents[i], '=');\n                            Attribute attribute;\n                            try {\n                                attribute = factory.createAttribute(response, charsetHeader, cleanString(values));\n                            } catch (NullPointerException | IllegalArgumentException e) {\n                                throw new ErrorDataDecoderException(e);\n                            }\n                            currentFieldAttributes.put(HttpHeaderValues.CHARSET, attribute);\n                        } else {\n                            Attribute attribute;\n                            try {\n                                attribute = factory.createAttribute(response,\n                                        cleanString(contents[0]), contents[i]);","sourceCodeStart":756,"sourceCodeEnd":792,"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#L756-L792","documentation":"The decoder encountered a nested 'multipart/mixed' Content-Type inside a part that is already being parsed as a mixed-multipart child. Nested mixed multiparts are not supported, so parsing fails with ErrorDataDecoderException. This protects the state machine from unsupported recursive multipart structures.","triggerScenarios":"A part within a multipart/mixed section itself declares Content-Type: multipart/mixed (currentStatus is DISPOSITION while already in mixed mode), so the state machine cannot transition to MIXEDDELIMITER twice.","commonSituations":"Servers implementing RFC-allowed but rarely-used nested multipart/mixed payloads (e.g. some email-like or SOAP-with-attachments stacks); middleware aggregating multipart payloads recursively.","solutions":["Flatten the payload on the server so mixed multipart is not nested inside another mixed multipart.","If nested mixed content is required, pre-process the raw body yourself (e.g. parse the outer layer and feed inner parts separately) instead of relying on the decoder.","Switch the parts to a simple multipart/form-data structure without the mixed wrapper.","File/track a feature request if your protocol genuinely needs nested mixed support."],"exampleFix":"// before (nested, unsupported)\nContent-Type: multipart/mixed; boundary=outer\r\n  Content-Type: multipart/mixed; boundary=inner\r\n// after (flattened)\nContent-Type: multipart/mixed; boundary=outer\r\n  Content-Type: application/octet-stream\r\n","handlingStrategy":"validation","validationCode":"// Detect nested multipart/mixed before sending the response\nif (isMixedMultipart(partContentType) && parentStatus == MIXED) {\n    throw new IllegalStateException(\"Nested multipart/mixed is not supported by the client decoder\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    response = client.multipartCall().await();\n} catch (BadRequestException e) {\n    if (e.getCause() instanceof ErrorDataDecoderException\n            && e.getCause().getMessage().contains(\"Mixed Multipart\")) {\n        // fall back to raw-body handling / custom parser\n        response = client.rawCall().await();\n    } else {\n        throw e;\n    }\n}","preventionTips":["Never nest multipart/mixed inside multipart/mixed in server responses.","Flatten attachments into a single-level multipart structure.","Document the decoder limitation for API producers targeting Quarkus clients.","Add a server-side test asserting single-level mixed parts."],"tags":["multipart","nested-multipart","unsupported-structure","resteasy-reactive"],"backgroundTag":"nested-multipart-unsupported","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}