quarkusio/quarkus · error · IllegalStateException

HTTP Security policy applied only on Quarkus REST cannot be

Error message

HTTP Security policy applied only on Quarkus REST cannot be run as 'RoutingContext' is null

What it means

The eager HTTP security path-matching policy (quarkus.http.auth.permission.* policies applied via Quarkus REST's JaxRsPathMatchingPolicy) requires access to the Vert.x RoutingContext. getPermissionCheck unwraps it from the request context; if absent, the check cannot run and IllegalStateException is thrown.

Source

Thrown at extensions/resteasy-reactive/rest/runtime/src/main/java/io/quarkus/resteasy/reactive/server/runtime/security/EagerSecurityContext.java:93

        // and write to a volatile variable during the request; the EagerSecurityHandler is created for each
        // endpoint (in case there is HTTP permission configured), so there can be a lot of them
        instance = this;
    }

    Uni<SecurityIdentity> getDeferredIdentity() {
        return Uni.createFrom().deferred(new Supplier<Uni<? extends SecurityIdentity>>() {
            @Override
            public Uni<SecurityIdentity> get() {
                return identityAssociation.get().getDeferredIdentity();
            }
        });
    }

    Uni<SecurityIdentity> getPermissionCheck(ResteasyReactiveRequestContext requestContext, SecurityIdentity identity,
            MethodDescription invokedMethodDesc) {
        final RoutingContext routingContext = requestContext.unwrap(RoutingContext.class);
        if (routingContext == null) {
            throw new IllegalStateException(
                    "HTTP Security policy applied only on Quarkus REST cannot be run as 'RoutingContext' is null");
        }
        record SecurityCheckWithIdentity(SecurityIdentity identity, HttpSecurityPolicy.CheckResult checkResult) {
        }
        return jaxRsPathMatchingPolicy
                .checkPermission(routingContext, identity == null ? getDeferredIdentity() : Uni.createFrom().item(identity),
                        invokedMethodDesc)
                .flatMap(new Function<HttpSecurityPolicy.CheckResult, Uni<? extends SecurityCheckWithIdentity>>() {
                    @Override
                    public Uni<SecurityCheckWithIdentity> apply(HttpSecurityPolicy.CheckResult checkResult) {
                        if (identity != null) {
                            return Uni.createFrom().item(new SecurityCheckWithIdentity(identity, checkResult));
                        }
                        if (checkResult.isPermitted() && checkResult.getAugmentedIdentity() == null) {
                            return Uni.createFrom().item(new SecurityCheckWithIdentity(null, checkResult));
                        }
                        // we need to resolve identity either to compare augmented identity or to determine
                        // whether the identity is anonymous (determines thrown exception for denied access)

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the security check only runs within a normal HTTP request handled by Quarkus REST (a RoutingContext is present)
  2. Do not invoke resource methods secured by HTTP permission policies outside the Vert.x request pipeline (e.g. in unit tests use QuarkusTest with a real HTTP call)
  3. Reorder custom handlers so the Vert.x unwrap is available when eager security runs
  4. If you don't need path-based HTTP permissions for this endpoint, scope the quarkus.http.auth.permission paths away from it

Example fix

// test: call over HTTP instead of invoking the method directly
// before
new MyResource().secured();
// after
given().when().get("/secured").then().statusCode(403);
Defensive patterns

Strategy: try-catch

Validate before calling

// before running the check, confirm a RoutingContext is available
RoutingContext rc = requestContext.unwrap(RoutingContext.class);
if (rc == null) {
    // skip HTTP-policy check or route the call through a real HTTP request
}

Type guard

RoutingContext rc = requestContext.unwrap(RoutingContext.class);
boolean hasRoutingContext = rc != null;

Try / catch

try {
    return securityContext.getPermissionCheck(requestContext, identity, methodDesc);
} catch (IllegalStateException e) {
    if (e.getMessage().contains("RoutingContext")) {
        // fall back to a policy not tied to RoutingContext or reject
    } else throw e;
}

Prevention

When it happens

Trigger: An HTTP permission policy (quarkus.http.auth.permission...) whose policy applies only on Quarkus REST is evaluated for a request whose ResteasyReactiveRequestContext cannot be unwrapped to a RoutingContext — e.g. the security check runs outside a normal Vert.x HTTP request flow.

Common situations: Invoking resource methods through non-HTTP dispatch paths or tests without a Vert.x context; custom security checks reusing EagerSecurityContext outside the standard request pipeline; misordered handlers stripping the context.

Related errors


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