quarkusio/quarkus · error · IllegalStateException

adding content to MultiByteHttpData is not supported

Error message

adding content to MultiByteHttpData is not supported

What it means

addContent(ByteBuf, boolean) is the standard Netty incremental-content entry point for HttpData, but MultiByteHttpData receives bytes only from its internal Multi<Byte> subscription. Calling addContent breaks the streaming protocol (buffer accounting, suspend/resume, done flag), so the class unconditionally throws IllegalStateException.

Source

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

                        paused = false;
                        resumption.run();
                    }
                });
    }

    void suspend(int awaitedBytes) {
        this.awaitedBytes = awaitedBytes;
        this.paused = true;
    }

    @Override
    public void setContent(ByteBuf buffer) throws IOException {
        throw new IllegalStateException("setting content of MultiByteHttpData is not supported");
    }

    @Override
    public void addContent(ByteBuf buffer, boolean last) throws IOException {
        throw new IllegalStateException("adding content to MultiByteHttpData is not supported");
    }

    @Override
    public void setContent(File file) throws IOException {
        throw new IllegalStateException("setting content of MultiByteHttpData is not supported");
    }

    @Override
    public void setContent(InputStream inputStream) throws IOException {
        throw new IllegalStateException("setting content of MultiByteHttpData is not supported");
    }

    @Override
    public void delete() {
        // do nothing
    }

    @Override

View on GitHub (pinned to e1c734241f)

Solutions

  1. Do not call addContent; let the Multi<Byte> passed to the part constructor drive the data.
  2. If you already have ByteBuf/byte[] chunks, convert them to a Multi<Byte> (e.g. Multi.createFrom().iterable of chunks) and pass it as the part body.
  3. Use a non-streaming part (byte[], File, Path, InputStream-backed) when you don't need reactive streaming.
  4. Ensure only PausableHttpPostRequestEncoder manipulates these parts; it never calls addContent.

Example fix

// before
httpData.addContent(Unpooled.wrappedBuffer(chunk), false);
// after
Multi<Byte> body = Multi.createFrom().iterable(chunks) // List<byte[]>
        .onItem().transformToMultiAndMerge(bytes -> Multi.createFrom().items(bytes));
// pass `body` as the streaming part content instead
Defensive patterns

Strategy: validation

Validate before calling

if (data instanceof MultiByteHttpData) {
    throw new IllegalArgumentException("Do not call addContent on MultiByteHttpData; bytes come from its Multi<Byte>");
}
data.addContent(buf, last);

Type guard

boolean supportsAddContent(InterfaceHttpData data) {
    return !(data instanceof MultiByteHttpData);
}

Try / catch

try {
    data.addContent(buf, last);
} catch (IllegalStateException e) {
    if (e.getMessage() != null && e.getMessage().contains("not supported")) {
        // feed chunks via a Multi<Byte> part instead
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Invoking addContent(buffer, last) on a MultiByteHttpData, e.g. by Netty's default HttpPostRequestEncoder path or custom code that appends chunks to multipart parts.

Common situations: Using a generic Netty multipart encoder on RESTEasy Reactive client parts; code paths that branch on FileUpload but assume Netty's MemoryFileUpload semantics; migrating legacy client code that piped ByteBuf chunks into uploads.

Related errors


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