quarkusio/quarkus · error · IllegalStateException
Cannot be called from response filter
Error message
Cannot be called from response filter
What it means
ContainerRequestContext methods that mutate request state (setEntityStream, setSecurityContext, abortWith) are forbidden in response filters per JAX-RS. ContainerRequestContextImpl.assertNotResponse throws IllegalStateException if the context is being used as a ContainerResponseContext phase, preventing illegal mutation of an already-processed request.
Source
Thrown at independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/jaxrs/ContainerRequestContextImpl.java:95
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);
}
@Override
public boolean containsHeaderString(String name, String valueSeparatorRegex, Predicate<String> valuePredicate) {
return quarkusRestContext.getHttpHeaders().containsHeaderString(name, valueSeparatorRegex, valuePredicate);
}
View on GitHub (pinned to e1c734241f)
Solutions
- Move abortWith/setEntityStream/setSecurityContext calls into a ContainerRequestFilter (pre or post match)
- In a response filter, mutate the ContainerResponseContext instead (e.g. setEntity, setStatus)
- Guard shared code with an instanceof/phase check before mutating request state
- Use requestContext.abortWith only before the response chain begins
Example fix
// before
public class MyFilter implements ContainerResponseFilter {
public void filter(ContainerRequestContext req, ContainerResponseContext res) {
req.abortWith(Response.ok().build()); // fails
}
}
// after
public class MyFilter implements ContainerResponseFilter {
public void filter(ContainerRequestContext req, ContainerResponseContext res) {
res.setStatus(200);
}
} Defensive patterns
Strategy: validation
Validate before calling
if (this instanceof ContainerResponseFilter) {
// never call abortWith/setEntityStream/setSecurityContext here
} Try / catch
try { ctx.abortWith(resp); } catch (IllegalStateException e) { if (e.getMessage().contains("response filter")) { responseCtx.setStatus(resp.getStatus()); } else { throw e; } } Prevention
- Call abortWith only from request filters
- In response filters mutate ContainerResponseContext instead
- Avoid sharing mutating code between request and response filter paths
When it happens
Trigger: Calling ctx.abortWith(...), ctx.setEntityStream(...), or ctx.setSecurityContext(...) inside a ContainerResponseFilter, or inside a request filter running in the response phase (e.g. via shared code invoked from both).
Common situations: A single filter implementing both ContainerRequestFilter and ContainerResponseFilter sharing mutation code; trying to short-circuit in a response filter instead of the request filter; copy-pasted abortWith logic into the response filter.
Related errors
- Can only be called from a @PreMatch filter
- Suspend method '${targetMethod.name()} of class '${targetMet
- Cannot use the EntityManager/Session because neither a trans
- Cannot use the EntityManager/Session because no transaction
- Providing multiple BuiltInReaderOverrideBuildItem for the sa
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/080197d293ae7982.
Report an issue: GitHub.