{"record":{"id":"7e4a58e2392b9143","repo":"quarkusio/quarkus","slug":"error-decoding-charset-attribute-wrapped-nullpoin","errorCode":null,"errorMessage":"Error decoding charset attribute (wrapped NullPointerException/IllegalArgumentException)","messagePattern":"Error decoding charset 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":785,"sourceCode":"                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]);\n                            } catch (NullPointerException | IllegalArgumentException e) {\n                                throw new ErrorDataDecoderException(e);\n                            }\n                            currentFieldAttributes.put(attribute.getName(), attribute);\n                        }\n                    }\n                }\n            }\n        }\n        // Is it a FileUpload\n        Attribute filenameAttribute = currentFieldAttributes.get(HttpHeaderValues.FILENAME);","sourceCodeStart":767,"sourceCodeEnd":803,"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#L767-L803","documentation":"This ErrorDataDecoderException wraps a NullPointerException or IllegalArgumentException from factory.createAttribute() when decoding the charset parameter of a multipart disposition. The cleaned charset value was rejected (null/empty/illegal), aborting the multipart decode. It indicates a malformed charset= parameter in a Content-Disposition line.","triggerScenarios":"Within a mixed or plain multipart disposition, a parameter starting with 'charset' has an empty or invalid value after '=' (values = substringAfter gives empty/null), making createAttribute throw.","commonSituations":"Servers emitting 'charset=' with no value; broken template engines dropping the encoding value; custom clients copying headers incorrectly.","solutions":["Fix the server to emit a valid charset value, e.g. charset=\"UTF-8\", or omit the parameter entirely.","Log/inspect the raw part headers to find the empty charset parameter.","Sanitize the payload upstream (proxy or middleware) if the server cannot be changed.","Ensure the client and server agree on encoding and rely on the default charset instead of sending charset explicitly."],"exampleFix":"// before\nContent-Disposition: form-data; name=\"txt\"; charset=\n// after\nContent-Disposition: form-data; name=\"txt\"; charset=\"UTF-8\"","handlingStrategy":"validation","validationCode":"// Validate charset parameter before emitting it\nString charset = params.get(\"charset\");\nif (charset != null && (charset.isBlank() || !Charset.isSupported(charset.trim().replace(\"\\\"\", \"\")))) {\n    throw new IllegalStateException(\"Invalid charset disposition parameter: '\" + charset + \"'\");\n}","typeGuard":"static boolean isValidCharsetParam(String v) {\n    return v != null && !v.isBlank() && Charset.isSupported(v.trim().replace(\"\\\"\", \"\"));\n}","tryCatchPattern":"try {\n    decode(responseBody);\n} catch (ErrorDataDecoderException e) {\n    log.warn(\"Bad charset disposition attribute: {}\", e.getCause(), e);\n    throw new BadRequestException(\"Malformed charset parameter in multipart response\", e);\n}","preventionTips":["Only send charset when a real value exists; never emit an empty 'charset='.","Stick to UTF-8 for text parts.","Quote parameter values in Content-Disposition.","Round-trip test: server emits, client decodes, in CI."],"tags":["multipart","charset","decoding","resteasy-reactive"],"backgroundTag":"multipart-decode-failed","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"}