{"record":{"id":"44e5955db98b7f9a","repo":"quarkusio/quarkus","slug":"error-decoding-content-disposition-attribute-wrap","errorCode":null,"errorMessage":"Error decoding content-disposition attribute (wrapped NullPointerException/IllegalArgumentException)","messagePattern":"Error decoding content-disposition attribute \\(wrapped NullPointerException/IllegalArgumentException\\)","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":740,"sourceCode":"            }\n            String[] contents = splitMultipartHeader(newline);\n            if (HttpHeaderNames.CONTENT_DISPOSITION.contentEqualsIgnoreCase(contents[0])) {\n                boolean checkSecondArg;\n                if (currentStatus == MultiPartStatus.DISPOSITION) {\n                    checkSecondArg = HttpHeaderValues.FORM_DATA.contentEqualsIgnoreCase(contents[1]);\n                } else {\n                    checkSecondArg = HttpHeaderValues.ATTACHMENT.contentEqualsIgnoreCase(contents[1])\n                            || HttpHeaderValues.FILE.contentEqualsIgnoreCase(contents[1]);\n                }\n                if (checkSecondArg) {\n                    // read next values and store them in the map as Attribute\n                    for (int i = 2; i < contents.length; i++) {\n                        String[] values = contents[i].split(\"=\", 2);\n                        Attribute attribute;\n                        try {\n                            attribute = getContentDispositionAttribute(values);\n                        } catch (NullPointerException | IllegalArgumentException e) {\n                            throw new ErrorDataDecoderException(e);\n                        }\n                        currentFieldAttributes.put(attribute.getName(), attribute);\n                    }\n                }\n            } else if (HttpHeaderNames.CONTENT_TRANSFER_ENCODING.contentEqualsIgnoreCase(contents[0])) {\n                Attribute attribute;\n                try {\n                    attribute = factory.createAttribute(response, HttpHeaderNames.CONTENT_TRANSFER_ENCODING.toString(),\n                            cleanString(contents[1]));\n                } catch (NullPointerException | IllegalArgumentException e) {\n                    throw new ErrorDataDecoderException(e);\n                }\n\n                currentFieldAttributes.put(HttpHeaderNames.CONTENT_TRANSFER_ENCODING, attribute);\n            } else if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(contents[0])) {\n                Attribute attribute;\n                try {\n                    attribute = factory.createAttribute(response, HttpHeaderNames.CONTENT_LENGTH.toString(),","sourceCodeStart":722,"sourceCodeEnd":758,"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#L722-L758","documentation":"While parsing the Content-Disposition header of a multipart part, each extra parameter (after the first two tokens) is converted via getContentDispositionAttribute; a NullPointerException or IllegalArgumentException there (missing '=', empty/invalid parameter, missing name) is wrapped into ErrorDataDecoderException.","triggerScenarios":"A Content-Disposition header with malformed extra parameters, e.g. 'form-data; name' (no '='), 'form-data; =value', or a filename/name parameter that the strict parser rejects.","commonSituations":"Non-conformant servers emitting odd disposition parameters (e.g. 'filename*=' RFC 5987 variants the parser doesn't handle); proxies altering the header; hand-crafted responses in tests.","solutions":["Fix the sender to emit RFC-compliant Content-Disposition parameters, each as key=value","Remove or repair malformed parameters (e.g. bare 'name' without '=value')","If a non-ASCII filename is the culprit, encode it in a form the parser accepts (quoted ASCII)","Catch ErrorDataDecoderException and inspect the wrapped NPE/IAE cause to pinpoint the bad parameter"],"exampleFix":"// before (part header)\nContent-Disposition: form-data; name; filename=\n// after\nContent-Disposition: form-data; name=\"file1\"; filename=\"report.txt\"","handlingStrategy":"validation","validationCode":"for (String p : disposition.split(\";\")) {\n    p = p.trim();\n    if (!p.isEmpty() && !p.equals(\"form-data\") && !p.contains(\"=\")) {\n        throw new IllegalArgumentException(\"Malformed disposition param: \" + p);\n    }\n}","typeGuard":null,"tryCatchPattern":"try { decoder.offer(chunk); } catch (ErrorDataDecoderException e) { if (e.getCause() instanceof IllegalArgumentException) { log.error(\"Bad Content-Disposition parameter\", e); } }","preventionTips":["Emit RFC 6266/7587-compliant Content-Disposition headers","Quote parameter values containing special characters","Add server-side tests asserting disposition header shape"],"tags":["http","multipart","content-disposition"],"backgroundTag":"malformed-content-disposition","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}