quarkusio/quarkus · error · RestClientDefinitionException

Parameters and variables don't match on ${typeDef}::${method

Error message

Parameters and variables don't match on ${typeDef}::${method}

What it means

Thrown by verifyInterface during build as a RestClientDefinitionException when the @Path template variables (e.g. {id}) on a method don't match the set of @PathParam-annotated parameters. The number of declared path variables must equal the number of bound parameters.

Source

Thrown at extensions/resteasy-classic/resteasy-client/runtime/src/main/java/io/quarkus/restclient/runtime/QuarkusRestClientBuilder.java:637

            Set<String> allVariables = new HashSet<>(template.getPathParamNamesInDeclarationOrder());
            Map<String, Object> paramMap = new HashMap<>();
            for (Parameter p : method.getParameters()) {
                PathParam pathParam = p.getAnnotation(PathParam.class);
                if (pathParam != null) {
                    paramMap.put(pathParam.value(), "foobar");
                } else if (p.isAnnotationPresent(org.jboss.resteasy.annotations.jaxrs.PathParam.class)) {
                    org.jboss.resteasy.annotations.jaxrs.PathParam rePathParam = p
                            .getAnnotation(org.jboss.resteasy.annotations.jaxrs.PathParam.class);
                    String name = rePathParam.value() == null || rePathParam.value()
                            .length() == 0 ? p.getName() : rePathParam.value();
                    paramMap.put(name, "foobar");
                } else if (p.isAnnotationPresent(BeanParam.class)) {
                    verifyBeanPathParam(p.getType(), paramMap);
                }
            }

            if (allVariables.size() != paramMap.size()) {
                throw new RestClientDefinitionException(
                        "Parameters and variables don't match on " + typeDef + "::" + method.getName());
            }

            try {
                template.resolveTemplates(paramMap, false).build();
            } catch (IllegalArgumentException ex) {
                throw new RestClientDefinitionException(
                        "Parameter names don't match variable names on " + typeDef + "::" + method.getName(), ex);
            }

        }
    }

    @Override
    public Configuration getConfiguration() {
        return getConfigurationWrapper();
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Make each {variable} in @Path have exactly one @PathParam with the same name, and vice versa
  2. Remove unused @PathParam annotations or add the missing {var} to the @Path template
  3. If a value isn't a path segment, annotate it @QueryParam/@HeaderParam instead

Example fix

// before
@GET
@Path("/items/{id}")
Item get(@PathParam("itemId") String id); // mismatch
// after
@GET
@Path("/items/{id}")
Item get(@PathParam("id") String id);
Defensive patterns

Strategy: validation

Validate before calling

// Check each {var} in @Path has a matching @PathParam of the same name
Pattern p = Pattern.compile("\\{([^}]+)\\}");
for (Method m : MyClient.class.getMethods()) {
    Path path = m.getAnnotation(Path.class);
    if (path == null) continue;
    Set<String> vars = new HashSet<>();
    Matcher mm = p.matcher(path.value());
    while (mm.find()) vars.add(mm.group(1));
    Set<String> params = new HashSet<>();
    for (java.lang.reflect.Parameter par : m.getParameters()) {
        PathParam pp = par.getAnnotation(PathParam.class);
        if (pp != null) params.add(pp.value());
    }
    if (!vars.equals(params)) throw new IllegalStateException(m + ": path vars " + vars + " != params " + params);
}

Try / catch

try {
    client = builder.build(MyClient.class);
} catch (RestClientDefinitionException e) {
    if (e.getMessage().contains("Parameters and variables don't match")) {
        log.error("Fix @Path templates vs @PathParam on: {}", e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: A @Path contains a variable like {id} but no matching @PathParam method parameter; an extra @PathParam with no corresponding {var} in the template; BeanParam fields counted separately causing count mismatch.

Common situations: Renaming a path segment but forgetting to rename the @PathParam; typos causing variable and param names to diverge; adding a @QueryParam mistakenly annotated as @PathParam.

Related errors


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