quarkusio/quarkus · error · IllegalArgumentException

When using Multi as body parameter only Multi<io.vertx.core.

Error message

When using Multi as body parameter only Multi<io.vertx.core.buffer.Buffer> is supported

What it means

When a REST client method body parameter is a Multi (reactive stream), the generator supports only Multi<io.vertx.core.buffer.Buffer> because it streams raw bytes. A Multi of any other element type (e.g. Multi<String>, Multi<byte[]>) cannot be wired as the request body and triggers an IllegalArgumentException at build time.

Source

Thrown at extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java:1176

                                    methodCreator.getMethodParam(paramIdx), methodTarget, index,
                                    restClientInterface.getClassName(),
                                    methodCreator.getThis(),
                                    handleBeanParamMethod.getThis(),
                                    formParams, beanParamDescriptorsField, multipart,
                                    beanParam.type);

                            handleBeanParamMethod.returnValue(invocationBuilderRef);
                            invocationBuilderEnrichers.put(handleBeanParamDescriptor, methodCreator.getMethodParam(paramIdx));
                        } else if (param.parameterType == ParameterType.PATH) {
                            // methodTarget = methodTarget.resolveTemplate(paramname, paramvalue);
                            addPathParam(methodCreator, methodTarget, param.name, methodCreator.getMethodParam(paramIdx),
                                    param.type, methodCreator.getThis(),
                                    getGenericTypeFromArray(methodCreator, methodGenericParametersField, paramIdx),
                                    getAnnotationsFromArray(methodCreator, methodParamAnnotationsField, paramIdx));
                        } else if (param.parameterType == ParameterType.BODY) {
                            if (param.declaredType.equals(Multi.class.getName())) {
                                if (!param.signature.equals(MULTI_BUFFER_SIGNATURE)) {
                                    throw new IllegalArgumentException(
                                            "When using Multi as body parameter only Multi<io.vertx.core.buffer.Buffer> is supported");
                                }
                            }

                            // just store the index of parameter used to create the body, we'll use it later
                            bodyParameterIdx = paramIdx;
                        } else if (param.parameterType == ParameterType.HEADER) {
                            Type paramType = jandexMethod.parameterType(paramIdx);
                            Type effectiveParamType = paramType;
                            boolean isOptional = isOptional(paramType, index);
                            if (isOptional) {
                                effectiveParamType = Type.create(Object.class);
                                if (paramType.kind() == PARAMETERIZED_TYPE) {
                                    Type objectType = paramType.asParameterizedType().arguments().get(0);
                                    if ((objectType.kind() == CLASS) || (objectType.kind() == PARAMETERIZED_TYPE)) {
                                        effectiveParamType = objectType;
                                    }
                                }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Change the parameter to Multi<io.vertx.core.buffer.Buffer> and encode elements yourself (e.g. Buffer.buffer(str))
  2. Use Uni<String>/String for small bodies, or Multi<Buffer> after mapping: multi.map(Buffer::buffer)
  3. If sending JSON lines, wrap into Buffer before passing

Example fix

// before
Response post(Multi<String> body);
// after
Response post(Multi<io.vertx.core.buffer.Buffer> body); // map: multi.map(Buffer::buffer)
Defensive patterns

Strategy: validation

Validate before calling

static void assertMultiBuffer(Class<?> raw, Type generic) { if (raw == Multi.class) { var arg = ((ParameterizedType) generic).getActualTypeArguments()[0]; if (arg != io.vertx.core.buffer.Buffer.class) throw new IllegalStateException("Multi body must be Multi<Buffer>"); } }

Type guard

boolean isMultiBuffer(java.lang.reflect.Parameter p) { return !Multi.class.equals(p.getType()) || p.getParameterizedType() instanceof ParameterizedType pt && pt.getActualTypeArguments()[0] == io.vertx.core.buffer.Buffer.class; }

Try / catch

try { client.post(multi); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Multi<io.vertx.core.buffer.Buffer>")) { log.error("Map elements to Buffer before sending"); } throw e; }

Prevention

When it happens

Trigger: Declaring a REST client POST/PUT method with a body parameter of type Multi<X> where X is not io.vertx.core.buffer.Buffer, e.g. Multi<String> or Multi<byte[]>.

Common situations: Trying to stream lines from a file or Kafka as Multi<String>; assuming automatic element encoding; migrating from a Publisher<byte[]> API.

Related errors


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