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;
}
@OverrideView on GitHub (pinned to e1c734241f)
Solutions
- Ensure you are using the RESTEasy Classic client from Quarkus (rest-client / resteasy-client-jaxrs), not another JAX-RS client implementation.
- Call the invoker through the standard API: client.invocation(...).rx(MultiRxInvokerImpl.class) on a WebTarget built by ResteasyClient so the SyncInvoker is a ClientInvocationBuilder.
- 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
- Use Quarkus' RESTEasy Classic client, not another JAX-RS Client implementation
- Obtain invokers via WebTarget.request().rx(...) so the concrete builder type is preserved
- Avoid wrapping/proxying the SyncInvoker before passing it to the Multi invoker
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
- Expected a ClientInvocationBuilder
- Negotiation or dynamic media type resolution for Multi is on
- dummy2
- Offending class is '${className}'
- Cannot serialise field '${i.getName()}' on object '${param}'
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/aa4d87214ec0ab7d.
Report an issue: GitHub.