quarkusio/quarkus · error · IllegalStateException
Unsupported type '${jaxRSAnnotationOfParam.name()}' used as
Error message
Unsupported type '${jaxRSAnnotationOfParam.name()}' used as an annotation in constructor of class '${resourceDotName}' What it means
The generator for resource classes with non-default constructors only knows how to map @QueryParam, @PathParam, @MatrixParam and @CookieParam constructor annotations to request values. A parameter annotated with any other JAX-RS annotation (e.g. @HeaderParam or @Context) reaches the mapping switch's else branch and throws this IllegalStateException.
Source
Thrown at extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/CustomResourceProducersGenerator.java:267
if (!parameterType.name().equals(ResteasyReactiveDotNames.STRING)) {
// TODO: do we need to support converters here?
throw new IllegalArgumentException("Parameter: " + i + " of the constructor of class '"
+ resourceDotName + "' which is annotated with '" + jaxRSAnnotationOfParam.name()
+ "' can only be of type String");
}
CtorParamData.CustomProducerParameterType customProducerParameterType;
if (jaxRSAnnotationOfParam.name().equals(ResteasyReactiveDotNames.QUERY_PARAM)) {
customProducerParameterType = CtorParamData.CustomProducerParameterType.QUERY;
} else if (jaxRSAnnotationOfParam.name().equals(ResteasyReactiveDotNames.HEADER_PARAM)) {
customProducerParameterType = CtorParamData.CustomProducerParameterType.HEADER;
} else if (jaxRSAnnotationOfParam.name().equals(ResteasyReactiveDotNames.PATH_PARAM)) {
customProducerParameterType = CtorParamData.CustomProducerParameterType.PATH;
} else if (jaxRSAnnotationOfParam.name().equals(ResteasyReactiveDotNames.MATRIX_PARAM)) {
customProducerParameterType = CtorParamData.CustomProducerParameterType.MATRIX;
} else if (jaxRSAnnotationOfParam.name().equals(ResteasyReactiveDotNames.COOKIE_PARAM)) {
customProducerParameterType = CtorParamData.CustomProducerParameterType.COOKIE;
} else {
throw new IllegalStateException("Unsupported type '" + jaxRSAnnotationOfParam.name()
+ "' used as an annotation in constructor of class '" + resourceDotName + "'");
}
String name = jaxRSAnnotationOfParam.value().asString(); // all the types we handle have the same annotation method
ctorParamData.add(new CtorParamData(customProducerParameterType, parameterType, name));
}
}
}
List<String> producerMethodParameterTypes = new ArrayList<>(ctor.parametersCount());
for (CtorParamData ctorParamDatum : ctorParamData) {
if (ctorParamDatum.getCustomProducerParameterType() == CtorParamData.CustomProducerParameterType.OTHER) {
producerMethodParameterTypes.add(ctorParamDatum.getParameterType().name().toString());
}
}
String methodName = "producer_" + resourceDotName.withoutPackagePrefix()
+ HashUtil.sha1(resourceDotName.toString());
try (MethodCreator m = c.getMethodCreator(methodName, resourceDotName.toString(),
producerMethodParameterTypes.toArray(new String[0]))) {View on GitHub (pinned to e1c734241f)
Solutions
- Restrict constructor parameter annotations to @QueryParam, @PathParam, @MatrixParam or @CookieParam
- Inject @HeaderParam/@Context values as method parameters or resource fields instead of constructor parameters
- Use @Inject of CDI beans (e.g. injected HttpHeaders/UriInfo providers) rather than JAX-RS @Context in the constructor
Example fix
// before
public MyResource(@HeaderParam("X-Tenant") String tenant) { ... }
// after
public MyResource() { ... }
public Response get(@HeaderParam("X-Tenant") String tenant) { ... } Defensive patterns
Strategy: validation
Validate before calling
Set<String> supported = Set.of("jakarta.ws.rs.QueryParam","jakarta.ws.rs.PathParam","jakarta.ws.rs.MatrixParam","jakarta.ws.rs.CookieParam");
for (Parameter p : ctor.getParameters()) {
for (Annotation a : p.getAnnotations()) {
String n = a.annotationType().getName();
if (n.startsWith("jakarta.ws.rs.") && !supported.contains(n))
throw new IllegalStateException(n + " is not supported on resource constructor parameters");
}
} Prevention
- Only use @QueryParam/@PathParam/@MatrixParam/@CookieParam in resource constructors
- Inject @HeaderParam and @Context values via method parameters or fields instead
- Use CDI @Inject for provider beans (HttpHeaders, UriInfo) rather than @Context in constructors
When it happens
Trigger: A resource class has a non-default constructor with a parameter annotated with @HeaderParam, @Context, @FormParam or another annotation that is not one of the four supported parameter annotations, and the annotation is treated as a JAX-RS parameter annotation during the build.
Common situations: Injecting headers via constructor because query/path worked in the constructor before; trying to @Context-inject UriInfo or HttpHeaders in a resource constructor.
Related errors
- Parameter: ${i} of the constructor of class '${resourceDotNa
- Parameter: ${i} of the constructor of class '${resourceDotNa
- A resource class cannot be simultaneously annotated with '@C
- Unable to load context type: ${typeParam}
- Unknown type '${type}' used as an annotation in constructor
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/5a02751a49e2d276.
Report an issue: GitHub.