quarkusio/quarkus · error · RestClientDefinitionException

@ClientHeaderParam method

Error message

@ClientHeaderParam method ${className}#${methodName} has too many parameters, at most one parameter, header name, expected

What it means

The static method resolved from @ClientHeaderParam (valueFrom) must take either zero parameters, a single String (header name), or a single HeaderFiller-compatible context parameter. When invoked statically and the method has more parameters than allowed, generation fails with this error.

Solutions

  1. Reduce the method to zero args, one String arg, or one HeaderFiller-style context arg
  2. Wrap extra data in static state or a method-local lookup
  3. Implement ComputeParameters/return String interface form if more context is genuinely needed

Example fix

// before
static String token(String name, String env) { ... }
// after
static String token(String name) { ... }
Defensive patterns

Strategy: validation

Validate before calling

for (Method m : HeaderUtils.class.getDeclaredMethods()) {
    int n = m.getParameterCount();
    if (n > 1 || (n == 1 && m.getParameterTypes()[0] != String.class))
        throw new IllegalStateException(m + " too many/unsupported parameters for @ClientHeaderParam");
}

Prevention

When it happens

Trigger: valueFrom static method declared with 2+ parameters or an unsupported single type (not String and not the compute context type), discovered while emitting bytecode that invokes it statically.

Common situations: Adding extra arguments (config, request id) to a header-fill helper; the Quarkus build fails for the whole app.

Related errors


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

Appendix: source

Thrown at extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/MicroProfileRestClientEnricher.java:908

                    if (accessibleType == AccessibleType.STATIC_METHOD) {
                        supplier = new Supplier<ResultHandle>() {
                            @Override
                            public ResultHandle get() {

                                if (headerFillingMethod.parametersCount() == 0) {
                                    return fillHeader.invokeStaticMethod(headerFillingMethod);
                                } else if (headerFillingMethod.parametersCount() == 1
                                        && isString(headerFillingMethod.parameterType(0))) {
                                    return fillHeader.invokeStaticMethod(headerFillingMethod, fillHeader.load(headerName));
                                } else if (headerFillingMethod.parametersCount() == 1
                                        && isComputedParamContext(headerFillingMethod.parameterType(0))) {
                                    ResultHandle fillerParam = fillHeader
                                            .newInstance(
                                                    COMPUTER_PARAM_CONTEXT_IMPL_CTOR,
                                                    fillHeader.load(headerName), requestContext);
                                    return fillHeader.invokeStaticMethod(headerFillingMethod, fillerParam);
                                } else {
                                    throw new RestClientDefinitionException(
                                            "@ClientHeaderParam method " + headerFillingMethod.declaringClass().toString() + "#"
                                                    + headerFillingMethod.name()
                                                    + " has too many parameters, at most one parameter, header name, expected");
                                }

                            }
                        };
                    } else if (accessibleType == AccessibleType.INTERFACE_METHOD) {
                        supplier = new Supplier<ResultHandle>() {
                            @Override
                            public ResultHandle get() {

                                String mockName = mockInterface(declaringClass, generatedClasses, index);
                                ResultHandle interfaceMock = fillHeader.newInstance(MethodDescriptor.ofConstructor(mockName));

                                if (headerFillingMethod.parametersCount() == 0) {
                                    return fillHeader.invokeInterfaceMethod(headerFillingMethod, interfaceMock);
                                } else if (headerFillingMethod.parametersCount() == 1

View on GitHub (pinned to e1c734241f)