quarkusio/quarkus · error · IllegalStateException
Can only be called from a @PreMatch filter
Error message
Can only be called from a @PreMatch filter
What it means
Per JAX-RS, ContainerRequestContext.setRequestUri and setMethod may only be invoked from @PreMatch ContainerRequestFilters (before resource routing). ContainerRequestContextImpl.assertPreMatch checks the isPreMatch flag and throws IllegalStateException otherwise, because changing URI/method after routing would invalidate the match.
Source
Thrown at independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/jaxrs/ContainerRequestContextImpl.java:89
@Override
public Request getRequest() {
return quarkusRestContext.getRequest();
}
@Override
public String getMethod() {
return quarkusRestContext.getMethod();
}
@Override
public void setMethod(String method) {
assertPreMatch();
quarkusRestContext.setMethod(method);
}
public void assertPreMatch() {
if (!isPreMatch()) {
throw new IllegalStateException("Can only be called from a @PreMatch filter");
}
}
public void assertNotResponse() {
if (isResponse()) {
throw new IllegalStateException("Cannot be called from response filter");
}
}
@Override
public MultivaluedMap<String, String> getHeaders() {
return quarkusRestContext.getHttpHeaders().getMutableHeaders();
}
@Override
public String getHeaderString(String name) {
return quarkusRestContext.getHttpHeaders().getHeaderString(name);
}View on GitHub (pinned to e1c734241f)
Solutions
- Annotate the ContainerRequestFilter class with @PreMatch so it runs before routing
- Move URI/method rewriting logic into the pre-match filter
- If rewriting after match is required, throw a redirection or use a different mechanism (e.g. abortWith a redirect Response)
- Verify no duplicate filter registration changes its phase
Example fix
// before
@Provider
public class RewriteFilter implements ContainerRequestFilter {
public void filter(ContainerRequestContext ctx) {
ctx.setRequestUri(new URI("/new")); // fails
}
}
// after
@PreMatch
@Provider
public class RewriteFilter implements ContainerRequestFilter {
public void filter(ContainerRequestContext ctx) {
ctx.setRequestUri(new URI("/new"));
}
} Defensive patterns
Strategy: validation
Validate before calling
if (!isPreMatchPhase(filter)) {
throw new IllegalStateException("setRequestUri/setMethod require @PreMatch");
} Type guard
static boolean isPreMatchFilter(Class<?> f) {
return f.isAnnotationPresent(jakarta.ws.rs.container.PreMatch.class);
} Try / catch
try { ctx.setRequestUri(newUri); } catch (IllegalStateException e) { if (e.getMessage().contains("@PreMatch")) { /* move logic to pre-match filter or redirect */ } throw e; } Prevention
- Annotate any filter that rewrites URI or method with @PreMatch
- Keep post-match filters read-only for routing info
- Review filter phase after adding @NameBinding or @Priority
When it happens
Trigger: Calling requestContext.setRequestUri(...) or setMethod(...) from a filter registered without @PreMatch (i.e. a post-match filter running after routing), or from a response filter.
Common situations: Adding @Priority only and assuming pre-match semantics; rewriting URLs for legacy redirects in a named/@NameBinding filter that lost @PreMatch; framework upgrades changing filter phase classification.
Related errors
- Cannot be called from response filter
- Cannot use the EntityManager/Session because neither a trans
- Cannot use the EntityManager/Session because no transaction
- Providing multiple BuiltInReaderOverrideBuildItem for the sa
- @Compressed and @Uncompressed cannot be both declared on res
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/40d0b48889483a89.
Report an issue: GitHub.