quarkusio/quarkus · error · ProcessingException

Expected a ClientInvocationBuilder

Error message

Expected a ClientInvocationBuilder

What it means

MultiRxInvokerImpl is Quarkus' reactive invoker for RESTEasy Client and only works with RESTEasy's concrete ClientInvocationBuilder, which exposes the internals needed for streaming a Multi. The constructor type-checks the SyncInvoker argument and throws this ProcessingException if it is any other SyncInvoker implementation (e.g. a plain Jersey-style or wrapper invoker). It indicates the reactive client extension is being used with an incompatible client stack.

Source

Thrown at extensions/resteasy-classic/resteasy-mutiny-common/runtime/src/main/java/io/quarkus/resteasy/mutiny/common/runtime/MultiRxInvokerImpl.java:32

import jakarta.ws.rs.sse.SseEventSource;

import org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder;
import org.jboss.resteasy.plugins.providers.sse.InboundSseEventImpl;
import org.jboss.resteasy.plugins.providers.sse.client.SseEventSourceImpl;

import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.subscription.BackPressureStrategy;

public class MultiRxInvokerImpl implements MultiRxInvoker {

    private static Object monitor = new Object();
    private ClientInvocationBuilder syncInvoker;
    private ScheduledExecutorService executorService;
    private BackPressureStrategy backpressureStrategy = BackPressureStrategy.BUFFER;

    public MultiRxInvokerImpl(final SyncInvoker syncInvoker, final ExecutorService executorService) {
        if (!(syncInvoker instanceof ClientInvocationBuilder)) {
            throw new ProcessingException("Expected a ClientInvocationBuilder");
        }
        this.syncInvoker = (ClientInvocationBuilder) syncInvoker;
        if (executorService instanceof ScheduledExecutorService) {
            this.executorService = (ScheduledExecutorService) executorService;
        }
    }

    @Override
    public BackPressureStrategy getBackPressureStrategy() {
        return backpressureStrategy;
    }

    @Override
    public void setBackPressureStrategy(BackPressureStrategy strategy) {
        this.backpressureStrategy = strategy;
    }

    @Override

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure you are using the RESTEasy Classic client from Quarkus (rest-client / resteasy-client-jaxrs), not another JAX-RS client implementation.
  2. Call the invoker through the standard API: client.invocation(...).rx(MultiRxInvokerImpl.class) on a WebTarget built by ResteasyClient so the SyncInvoker is a ClientInvocationBuilder.
  3. If you must construct it manually, pass builder from ResteasyClient.target(...).request() castable to ClientInvocationBuilder, or check instanceof before constructing.

Example fix

// before
MultiRxInvokerImpl invoker = new MultiRxInvokerImpl(someGenericSyncInvoker, exec); // ProcessingException

// after
ResteasyClient client = (ResteasyClient) ClientBuilder.newClient();
ClientInvocationBuilder sync = (ClientInvocationBuilder) client.target(url).request();
MultiRxInvokerImpl invoker = new MultiRxInvokerImpl(sync, exec);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(syncInvoker instanceof ClientInvocationBuilder)) {
    throw new IllegalStateException("MultiRxInvokerImpl requires a RESTEasy ClientInvocationBuilder; got " + syncInvoker.getClass());
}

Type guard

static boolean supportsMulti(SyncInvoker invoker) {
    return invoker instanceof org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder;
}

Try / catch

try {
    MultiRxInvokerImpl invoker = new MultiRxInvokerImpl(syncInvoker, exec);
} catch (ProcessingException e) {
    if (e.getMessage().contains("Expected a ClientInvocationBuilder")) {
        throw new IllegalStateException("Use the RESTEasy Classic client so rx() receives a ClientInvocationBuilder", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructing new MultiRxInvokerImpl(syncInvoker, executorService) — directly or via client.rx(MultiRxInvokerImpl.class) — when syncInvoker is not an instance of org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder.

Common situations: Using the Quarkus RESTEasy Reactive client extensions (resteasy-mutiny) on the wrong client implementation on the classpath (e.g. standard JAX-RS client from another provider), or calling RxInvoker APIs through a wrapped/proxied invoker.

Related errors


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