quarkusio/quarkus · error · ErrorDataEncoderException

Header already encoded

Error message

Header already encoded

What it means

finalizeRequest() can only finalize headers once; calling it again after headerFinalized is true throws ErrorDataEncoderException("Header already encoded"). It enforces the encoder's one-shot finalization contract.

Source

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

     */
    public HttpRequest finalizeRequest() throws ErrorDataEncoderException {
        // Finalize the multipartHttpDatas
        if (!headerFinalized) {
            if (isMultipart) {
                QuarkusInternalAttribute internal = new QuarkusInternalAttribute(charset);
                if (duringMixedMode) {
                    internal.addValue("\r\n--" + multipartMixedBoundary + "--");
                }
                internal.addValue("\r\n--" + multipartDataBoundary + "--\r\n");
                multipartHttpDatas.add(internal);
                multipartMixedBoundary = null;
                currentFileUpload = null;
                duringMixedMode = false;
                globalBodySize += internal.size();
            }
            headerFinalized = true;
        } else {
            throw new ErrorDataEncoderException("Header already encoded");
        }

        HttpHeaders headers = request.headers();
        List<String> contentTypes = headers.getAll(HttpHeaderNames.CONTENT_TYPE);
        if (contentTypes != null) {
            headers.remove(HttpHeaderNames.CONTENT_TYPE);
            for (String contentType : contentTypes) {
                // "multipart/form-data; boundary=--89421926422648"
                String lowercased = contentType.toLowerCase();
                if (lowercased.startsWith(HttpHeaderValues.MULTIPART_FORM_DATA.toString()) ||
                        lowercased.startsWith(HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString())) {
                    // ignore
                } else {
                    headers.add(HttpHeaderNames.CONTENT_TYPE, contentType);
                }
            }
        }
        if (isMultipart) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Create a fresh encoder (and re-add body data) for each send/retry
  2. Guard finalizeRequest with a boolean so it runs once per encoder
  3. Only call finalizeRequest at the outermost request-building layer

Example fix

// before
encoder.finalizeRequest();
// retry path
encoder.finalizeRequest(); // throws
// after
encoder.finalizeRequest();
// retry path
PausableHttpPostRequestEncoder encoder2 = new PausableHttpPostRequestEncoder(request, true, charset, factory, mode);
Defensive patterns

Strategy: try-catch

Validate before calling

if (encoder.isFinalized()) { encoder = newEncoderFrom(request, bodyData); } else { encoder.finalizeRequest(); }

Type guard

null

Try / catch

try { encoder.finalizeRequest(); } catch (ErrorDataEncoderException e) { /* already finalized: reuse or rebuild */ }

Prevention

When it happens

Trigger: Calling finalizeRequest() twice on the same encoder instance, e.g. on retry or when sending the same request twice.

Common situations: Retry logic that re-invokes finalizeRequest on the original encoder; shared helper methods that each call finalize.

Related errors


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