quarkusio/quarkus · error · RestClientDefinitionException
Invalid @ClientHeaderParam definition, method parameter %s i
Error message
Invalid @ClientHeaderParam definition, method parameter %s is not of String type. Problematic interface: %s
What it means
If the @ClientHeaderParam value is not a static method reference, it is treated as a method-parameter reference (a name matching a parameter of the annotated client method). If a matching parameter is found but its type is not String, the enricher rejects it since header values must be strings.
Source
Thrown at extensions/resteasy-reactive/rest-client/deployment/src/main/java/io/quarkus/rest/client/reactive/deployment/MicroProfileRestClientEnricher.java:871
"Invalid %s definition, unable to determine class %s. Problematic interface: %s",
CLIENT_HEADER_PARAM, className, declaringClass));
}
headerFillingMethod = findMethod(clazz, declaringClass, staticMethodName,
CLIENT_HEADER_PARAM.toString());
} else {
headerFillingMethod = findMethod(declaringClass, declaringClass, accessibleName,
CLIENT_HEADER_PARAM.toString());
}
Type valueType = null;
AtomicInteger parameterPosition = new AtomicInteger(-1);
if (headerFillingMethod == null) {
for (MethodParameterInfo parameter : declaringMethod.parameters()) {
if (!accessibleName.equals(parameter.name())) {
continue;
}
if (!isString(parameter.type())) {
throw new RestClientDefinitionException(String.format(
"Invalid %s definition, method parameter %s is not of String type. Problematic interface: %s",
CLIENT_HEADER_PARAM, accessibleName, declaringClass));
}
accessibleType = AccessibleType.METHOD_PARAMETER;
valueType = parameter.type();
parameterPosition.set(parameter.position());
break;
}
if (valueType == null) {
throw new RestClientDefinitionException(String.format(
"Invalid %s definition, unable to determine target method '%s'. Problematic interface: %s",
CLIENT_HEADER_PARAM, accessibleName, declaringClass));
}
} else {
valueType = headerFillingMethod.returnType();
}
Supplier<ResultHandle> supplier;View on GitHub (pinned to e1c734241f)
Solutions
- Change the client method parameter type to String
- Convert at the call site before invoking the client method
- Use a valueFrom static method that formats the value instead
Example fix
// before
String get(@PathParam("id") UUID userId);
// after
String get(@PathParam("id") String userId); Defensive patterns
Strategy: type-guard
Validate before calling
boolean isStringParam(java.lang.reflect.Executable m, String name) {
for (java.lang.reflect.Parameter p : m.getParameters())
if (p.getName().equals(name)) return p.getType() == String.class;
return false;
} Type guard
static boolean isStringParameter(java.lang.reflect.Method m, String paramName) {
return java.util.Arrays.stream(m.getParameters())
.anyMatch(p -> p.getName().equals(paramName) && p.getType() == String.class);
} Prevention
- Use String parameters for any value referenced by {placeholder} annotations
- Keep annotation placeholders and parameter names in sync
- Prefer valueFrom static methods when non-String types must be formatted
When it happens
Trigger: @ClientHeaderParam(name="X", value="{userId}") on a method whose parameter userId is Integer/UUID/Object rather than String.
Common situations: Using numeric or UUID path/body parameters as header sources; developers assume automatic toString conversion.
Related errors
- Unable to determine the proper baseUrl/baseUri. Consider reg
- Duplicate ${annotationName} annotation for parameter: ${name
- Class ${className} used in ${annotationName} on ${declaringC
- ${annotationName} method ${declaringClass}#${staticMethodNam
- ${annotationName} method ${methodName} not found on ${declar
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/49eaabf9b00b238a.
Report an issue: GitHub.