quarkusio/quarkus · error · RestClientDefinitionException
Ambiguous @HttpMethod definition on type ${typeDef}
Error message
Ambiguous @HttpMethod definition on type ${typeDef} What it means
Thrown by QuarkusRestClientBuilder.verifyInterface (during build) as a RestClientDefinitionException when a resource interface method carries more than one HTTP method annotation (@GET, @POST, @PUT, @DELETE, etc.). Each interface method must declare exactly one HTTP verb.
Source
Thrown at extensions/resteasy-classic/resteasy-client/runtime/src/main/java/io/quarkus/restclient/runtime/QuarkusRestClientBuilder.java:590
paramMap.put(name, "foobar");
}
}
}
private <T> void verifyInterface(Class<T> typeDef) {
Method[] methods = resolveMethods(typeDef);
// multiple verbs
for (Method method : methods) {
boolean hasHttpMethod = false;
for (Annotation annotation : method.getAnnotations()) {
boolean isHttpMethod = (annotation.annotationType().getAnnotation(HttpMethod.class) != null);
if (!hasHttpMethod && isHttpMethod) {
hasHttpMethod = true;
} else if (hasHttpMethod && isHttpMethod) {
throw new RestClientDefinitionException("Ambiguous @HttpMethod definition on type " + typeDef);
}
}
}
// invalid parameter
Path classPathAnno = typeDef.getAnnotation(Path.class);
ResteasyUriBuilder template = null;
for (Method method : methods) {
Path methodPathAnno = method.getAnnotation(Path.class);
if (methodPathAnno != null) {
template = classPathAnno == null
? (ResteasyUriBuilder) new ResteasyUriBuilderImpl().path(methodPathAnno.value())
: (ResteasyUriBuilder) new ResteasyUriBuilderImpl()
.path(classPathAnno.value() + "/" + methodPathAnno.value());
} else if (classPathAnno != null) {
template = (ResteasyUriBuilder) new ResteasyUriBuilderImpl().path(classPathAnno.value());
} else {View on GitHub (pinned to e1c734241f)
Solutions
- Keep exactly one HTTP method annotation per interface method — remove the extra one
- If a custom verb is needed, ensure it doesn't stack with a standard annotation
- Verify with the MicroProfile spec: one @HttpMethod meta-annotated annotation per resource method
Example fix
// before
@GET
@POST
@Path("/items")
List<Item> getItems();
// after
@GET
@Path("/items")
List<Item> getItems(); Defensive patterns
Strategy: validation
Validate before calling
for (Method m : MyClient.class.getMethods()) {
long count = Arrays.stream(m.getAnnotations())
.filter(a -> a.annotationType().isAnnotationPresent(HttpMethod.class))
.count();
if (count > 1) throw new IllegalStateException(m + " has multiple HTTP method annotations");
} Try / catch
try {
client = builder.build(MyClient.class);
} catch (RestClientDefinitionException e) {
if (e.getMessage().startsWith("Ambiguous @HttpMethod definition")) {
log.error("Interface method has two HTTP verb annotations: {}", e.getMessage());
}
throw e;
} Prevention
- Exactly one HTTP verb annotation per interface method
- After refactoring verbs, delete the old annotation, don't stack
- Code-review client interfaces for duplicate annotations
- Catch this with an early unit test that builds the client
When it happens
Trigger: Annotating one client interface method with two HTTP annotations (e.g. @GET and @POST); meta-annotations that accidentally both carry @HttpMethod; copy-paste leaving an old verb annotation in place.
Common situations: Refactoring @GET to @POST and keeping both; combining custom verb annotations with standard ones on the same method; IDE auto-import adding a second annotation.
Related errors
- Parameters and variables don't match on ${typeDef}::${method
- Parameter names don't match variable names on ${typeDef}::${
- 'quarkus-narayana-lra' can only work if 'quarkus-rest-client
- io.quarkus.oidc.client.OidcClientFilter annotation can be ap
- <INVOKED_METHOD_PROP> property must not be null
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/3266276fd1b2ecf4.
Report an issue: GitHub.