quarkusio/quarkus · error · IllegalArgumentException
Not a REST client interface: " + clazz + ". No @Path annotat
Error message
Not a REST client interface: " + clazz + ". No @Path annotation found on the class or any methods of the interface and no HTTP method annotations (@POST, @PUT, @GET, @HEAD, @DELETE, etc) found on any of the methods
What it means
The requested class has no generated client proxy and carries no REST client annotations at all, so it cannot be a REST client interface. ClientProxies.get() falls through to this IllegalArgumentException when the interface lacks @Path on itself or its methods and lacks any HTTP method annotation (@GET, @POST, @PUT, @HEAD, @DELETE, etc.).
Source
Thrown at independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientProxies.java:38
public ClientProxies(Map<Class<?>, BiFunction<WebTarget, List<ParamConverterProvider>, ?>> clientProxies,
Map<Class<?>, String> failures) {
this.clientProxies = clientProxies;
this.failures = failures;
}
public <T> T get(Class<?> clazz, WebTarget webTarget, List<ParamConverterProvider> providers) {
BiFunction<WebTarget, List<ParamConverterProvider>, ?> function = clientProxies.get(clazz);
if (function == null) {
String failure = failures.get(clazz);
if (failure != null) {
throw new InvalidRestClientDefinitionException(
"Failed to generate client for class " + clazz + " : " + failure);
} else {
if (hasRestClientAnnotations(clazz)) {
throw new IllegalStateException("REST client interface: " + clazz
+ " was not indexed at build time. See https://quarkus.io/guides/cdi-reference#bean_discovery for information on how to index the module that contains it.");
} else {
throw new IllegalArgumentException("Not a REST client interface: " + clazz + ". No @Path annotation " +
"found on the class or any methods of the interface and no HTTP method annotations " +
"(@POST, @PUT, @GET, @HEAD, @DELETE, etc) found on any of the methods");
}
}
}
//noinspection unchecked
return (T) function.apply(webTarget, providers);
}
private boolean hasRestClientAnnotations(Class<?> clazz) {
for (Annotation annotation : clazz.getAnnotations()) {
if (isRestClientAnnotation(annotation)) {
return true;
}
}
for (Method method : clazz.getDeclaredMethods()) {
for (Annotation annotation : method.getDeclaredAnnotations()) {
if (isRestClientAnnotation(annotation)) {View on GitHub (pinned to e1c734241f)
Solutions
- Annotate the interface with @Path (class or method level) and each method with an HTTP method annotation (@GET/@POST/@PUT/@DELETE/@HEAD)
- Verify you are passing the actual REST client interface, not a DTO/model interface
- Add @RegisterRestClient if using MicroProfile REST client configuration
- Rebuild after adding annotations so the build-time proxy generation picks it up
Example fix
// before
public interface ItemClient { Item get(String id); }
// after
@Path("/items")
@RegisterRestClient
public interface ItemClient {
@GET
@Path("/{id}")
Item get(@PathParam("id") String id);
} Defensive patterns
Strategy: validation
Validate before calling
// verify the interface is a valid REST client before building
static boolean isRestClientInterface(Class<?> c) {
if (!c.isInterface()) return false;
if (c.isAnnotationPresent(jakarta.ws.rs.Path.class)) return true;
for (Method m : c.getMethods()) {
if (m.isAnnotationPresent(jakarta.ws.rs.Path.class)) return true;
for (Annotation a : m.getAnnotations())
if (a.annotationType().getName().startsWith("jakarta.ws.rs.")) return true;
}
return false;
} Type guard
boolean isValidRestClient(Class<?> c) { return c.isInterface() && isRestClientInterface(c); } Try / catch
try {
return builder.build(clazz);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Not a REST client interface")) {
throw new ConfigurationException("Register the annotated client interface, not " + clazz, e);
}
throw e;
} Prevention
- Annotate the interface with @Path and methods with @GET/@POST/etc. before registering it
- Double-check you pass the client interface, not a DTO or model class
- Add @RegisterRestClient for MicroProfile-style configuration
- Cover every client interface with a startup build test
When it happens
Trigger: Passing a plain (unannotated) interface or class to QuarkusRestClientBuilder/ClientProxies.get() expecting a proxy to be created.
Common situations: Mistakenly registering the wrong interface (e.g. the API model class instead of the client); forgetting @Path or the @GET/@POST annotations on interface methods; refactor moved annotations off the interface; typos in package imports (wrong @Path).
Related errors
- Failed to generate client for class " + clazz + " : " + fail
- The @Blocking, @NonBlocking and @RunOnVirtualThread annotati
- Value not set for ${param}
- TransformedAnnotationsBuildItem#queryForMethodParam needs to
- No current Mutiny.Session found - you need to annotate your
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/9836a651032926db.
Report an issue: GitHub.