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
- Change the parameter to Multi<io.vertx.core.buffer.Buffer> and encode elements yourself (e.g. Buffer.buffer(str))
- Use Uni<String>/String for small bodies, or Multi<Buffer> after mapping: multi.map(Buffer::buffer)
- 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
- Always use Multi<io.vertx.core.buffer.Buffer> for streamed bodies
- Map elements: multi.map(Buffer::buffer) before passing
- Use Uni/String for non-streamed payloads
- Check the signature of Multi parameters against MULTI_BUFFER
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
- Specifying executor service is not supported. The underlying
- Unsupported field type for multipart response mapping: " + t
- Unsupported type '" + notBodyTargetType + "' used with '" +
- Array of unsupported type: " + typeStr + " on " + errorLocat
- not supported yet
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/b6fd4f7507172885.
Report an issue: GitHub.