quarkusio/quarkus · error · IllegalArgumentException
Only a single argument can be annotated with '" + URL + "'.
Error message
Only a single argument can be annotated with '" + URL + "'. Offending method is '" + jandexMethod.declaringClass().name() + "#" + jandexMethod.name()
What it means
In a generated REST client method, at most one parameter may carry the @BaseUrl annotation (which supplies the request's base URL). If two or more METHOD_PARAMETER targets of @BaseUrl are found on the interface method, bytecode generation aborts with an IllegalArgumentException identifying the offending method.
Source
Thrown at extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java:1029
MethodDescriptor.ofConstructor(ClientObservabilityHandler.class, String.class),
classContext.constructor.load(templatePath)));
}
// generate implementation for a method from jaxrs interface:
MethodCreator methodCreator = classContext.classCreator.getMethodCreator(method.getName(),
method.getSimpleReturnType(),
javaMethodParameters);
AssignableResultHandle methodTarget = methodCreator.createVariable(WebTarget.class);
methodCreator.assign(methodTarget,
methodCreator.readInstanceField(defaultWebTargetForMethod, methodCreator.getThis()));
// handle the @BaseUrl annotation
List<AnnotationInstance> notBodyAnnotations = jandexMethod.annotations(URL).stream()
.filter(ai -> ai.target().kind() == AnnotationTarget.Kind.METHOD_PARAMETER).toList();
if (!notBodyAnnotations.isEmpty()) {
if (notBodyAnnotations.size() > 1) {
throw new IllegalArgumentException(
"Only a single argument can be annotated with '" + URL
+ "'. Offending method is '"
+ jandexMethod.declaringClass().name() + "#" + jandexMethod.name());
}
// the idea here is to create a WebTarget that used the base URL provided by the user,
// along with the paths of the REST Client class and current method
MethodParameterInfo baseUrlMethodParam = notBodyAnnotations.get(0).target().asMethodParameter();
DotName notBodyTargetType = baseUrlMethodParam.type().name();
ResultHandle methodParam = methodCreator.getMethodParam(baseUrlMethodParam.position());
AssignableResultHandle newUri = methodCreator.createVariable(java.net.URI.class);
BytecodeCreator methodParamNotNull = methodCreator.ifNotNull(methodParam).trueBranch();
if (STRING.equals(notBodyTargetType)) {
methodParamNotNull.assign(newUri, methodParamNotNull.newInstance(URI_CTOR, methodParam));
} else if (ResteasyReactiveDotNames.URL.equals(notBodyTargetType)) {View on GitHub (pinned to e1c734241f)
Solutions
- Keep exactly one @BaseUrl-annotated parameter per client method
- Remove the redundant @BaseUrl from the extra parameter
- If multiple URL parts are needed, pass a single java.net.URL or String parameter and build the path inside it
Example fix
// before String get(@BaseUrl String base, @BaseUrl String alt, String id); // after String get(@BaseUrl String base, String id);
Defensive patterns
Strategy: validation
Validate before calling
long baseUrls = Arrays.stream(method.getParameters()).filter(p -> p.isAnnotationPresent(BaseUrl.class)).count(); if (baseUrls > 1) throw new IllegalStateException("Only one @BaseUrl parameter allowed on " + method); Type guard
boolean hasSingleBaseUrl(java.lang.reflect.Method m) { return Arrays.stream(m.getParameters()).filter(p -> p.isAnnotationPresent(BaseUrl.class)).count() == 1; } Try / catch
try { client.call(); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Only a single argument")) { log.error("Remove duplicate @BaseUrl parameter"); } throw e; } Prevention
- At most one @BaseUrl parameter per client method
- Audit client interfaces after merges/refactors
- Treat @BaseUrl as a singleton marker per method
- Add an architecture test scanning client interfaces
When it happens
Trigger: Annotating two or more parameters of the same REST client interface method with @BaseUrl, causing the notBodyAnnotations size check (> 1) to fail during client generation.
Common situations: Refactoring a client method to add another URL-like parameter without removing the original @BaseUrl; misunderstanding @BaseUrl as a per-part annotation; merging two client methods.
Related errors
- PartType annotation is only supported on fields and (setter/
- Unimplemented mode of use of 'io.quarkus.runtime.logging.Log
- 'quarkus-narayana-lra' can only work if 'quarkus-rest-client
- Not possible to define the scope %s for the REST client %s
- The combination of '@${annotationName}' and '@ServerRequestF
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/c9ba53574da7946f.
Report an issue: GitHub.