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

  1. Move abortWith/setEntityStream/setSecurityContext calls into a ContainerRequestFilter (pre or post match)
  2. In a response filter, mutate the ContainerResponseContext instead (e.g. setEntity, setStatus)
  3. Guard shared code with an instanceof/phase check before mutating request state
  4. 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

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


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