quarkusio/quarkus · error · IllegalArgumentException

Wrong Vert.x context used for multipart upload. Expected: "

Error message

Wrong Vert.x context used for multipart upload. Expected: " + context + ", actual: " + Vertx.currentContext()

What it means

QuarkusMultipartFormUpload.run() asserts that the encoding loop executes on the Vert.x context captured at construction time. If Vertx.currentContext() differs from the expected context it throws this IllegalArgumentException, because multipart encoding mutates shared Netty state that is not safe across contexts. This guards against the upload being driven from the wrong thread/context.

Source

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

            } else {
                return;
            }
        }
        handler.handle(item);
    }

    private void clearEncoder() {
        if (encoder == null) {
            return;
        }
        encoder.cleanFiles();
        encoder = null;
    }

    @Override
    public void run() {
        if (Vertx.currentContext() != context) {
            throw new IllegalArgumentException("Wrong Vert.x context used for multipart upload. Expected: " + context +
                    ", actual: " + Vertx.currentContext());
        }
        while (!ended) {
            if (encoder.isChunked()) {
                try {
                    HttpContent chunk = encoder.readChunk(ALLOC);
                    if (chunk == PausableHttpPostRequestEncoder.WAIT_MARKER) {
                        return; // resumption will be scheduled by encoder
                    } else if (chunk == LastHttpContent.EMPTY_LAST_CONTENT || encoder.isEndOfInput()) {
                        ended = true;
                        request = null;
                        clearEncoder();
                        pending.write(InboundBuffer.END_SENTINEL);
                    } else {
                        ByteBuf content = chunk.content();
                        Buffer buff = BufferInternal.buffer(content);
                        boolean writable = pending.write(buff);
                        if (!writable) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the multipart upload is driven on the original Vert.x context; do not wrap run() in executeBlocking or move it to another executor
  2. If work must happen elsewhere, hop back with context.runOnContext(v -> upload.run()) before encoding
  3. Let the REST client and Vert.x WebClient drive the request themselves instead of manually invoking the upload loop

Example fix

// before
workerExecutor.executeBlocking(promise -> {
    upload.run();
    promise.complete();
});
// after
context.runOnContext(v -> upload.run());
Defensive patterns

Strategy: try-catch

Validate before calling

if (Vertx.currentContext() != expectedContext) {
    expectedContext.runOnContext(v -> upload.run());
} else {
    upload.run();
}

Try / catch

try {
    upload.run();
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Wrong Vert.x context")) {
        expectedContext.runOnContext(v -> upload.run());
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling the upload's run()/drain logic from a different Vert.x context than the one that created the QuarkusMultipartFormUpload, e.g. scheduling the write loop on a worker thread or a different context via executeBlocking, custom thread pools, or resuming the request from another context.

Common situations: Offloading multipart encoding to a worker thread with executeBlocking; integrating the client with third-party reactive libraries that shift contexts; custom interceptors/filters that resume the HTTP request on the wrong context; version upgrades that changed which context the client runs on.

Related errors


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