quarkusio/quarkus · error · ErrorDataDecoderException

Error decoding multipart attribute (wrapped NullPointerExcep

Error message

Error decoding multipart attribute (wrapped NullPointerException/IllegalArgumentException)

What it means

This ErrorDataDecoderException wraps a NullPointerException or IllegalArgumentException thrown while creating a generic (non-charset) disposition attribute such as a custom name/value pair. The attribute factory rejected the cleaned name or value, so the decoder fails the multipart decode. It means some parameter in the Content-Disposition line could not be turned into a valid attribute.

Source

Thrown at independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/multipart/QuarkusMultipartResponseDecoder.java:794

                } else {
                    for (int i = 1; i < contents.length; i++) {
                        final String charsetHeader = HttpHeaderValues.CHARSET.toString();
                        if (contents[i].regionMatches(true, 0, charsetHeader, 0, charsetHeader.length())) {
                            String values = StringUtil.substringAfter(contents[i], '=');
                            Attribute attribute;
                            try {
                                attribute = factory.createAttribute(response, charsetHeader, cleanString(values));
                            } catch (NullPointerException | IllegalArgumentException e) {
                                throw new ErrorDataDecoderException(e);
                            }
                            currentFieldAttributes.put(HttpHeaderValues.CHARSET, attribute);
                        } else {
                            Attribute attribute;
                            try {
                                attribute = factory.createAttribute(response,
                                        cleanString(contents[0]), contents[i]);
                            } catch (NullPointerException | IllegalArgumentException e) {
                                throw new ErrorDataDecoderException(e);
                            }
                            currentFieldAttributes.put(attribute.getName(), attribute);
                        }
                    }
                }
            }
        }
        // Is it a FileUpload
        Attribute filenameAttribute = currentFieldAttributes.get(HttpHeaderValues.FILENAME);
        if (currentStatus == MultiPartStatus.DISPOSITION) {
            if (filenameAttribute != null) {
                // FileUpload
                currentStatus = MultiPartStatus.FILEUPLOAD;
                // do not change the buffer position
                return decodeMultipart(MultiPartStatus.FILEUPLOAD);
            } else {
                // Field
                currentStatus = MultiPartStatus.FIELD;

View on GitHub (pinned to e1c734241f)

Solutions

  1. Inspect the raw Content-Disposition line and fix the malformed parameter on the server.
  2. Ensure every ';'-separated token has a non-empty name and value.
  3. Remove non-standard parameters the decoder does not need.
  4. If needed, pre-normalize the response or use a permissive AttributeFactory implementation.

Example fix

// before (empty token/value)
Content-Disposition: form-data; ; name=; value="x"
// after
Content-Disposition: form-data; name="file"; value="x"
Defensive patterns

Strategy: validation

Validate before calling

// Validate each disposition token before serialization
tokens.forEach(t -> {
    if (t.name().isBlank() || t.value() == null || t.value().isBlank()) {
        throw new IllegalStateException("Empty disposition token: " + t);
    }
});

Type guard

static boolean hasValidTokens(String[] contents) {
    return contents != null && contents.length > 1
        && contents[0] != null && !contents[0].isBlank();
}

Try / catch

try {
    decoder.decodeMultipart(status);
} catch (ErrorDataDecoderException e) {
    log.warn("Unparseable disposition attribute: {}", e.getCause(), e);
    throw new MalformedMultipartException(e);
}

Prevention

When it happens

Trigger: An arbitrary disposition parameter (contents[0] as name, contents[i] as value) yields a null/empty name after cleanString, or contains characters that factory.createAttribute rejects, throwing NPE/IAE.

Common situations: Servers emitting unusual or malformed disposition parameters (e.g. 'name=' with empty value, stray semicolons producing empty tokens); custom headers injected into Content-Disposition by middleware.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/e3760a93de3802ed. Report an issue: GitHub.