{"record":{"id":"7f49b13007b9f4e1","repo":"quarkusio/quarkus","slug":"blocking-security-check-attempted-in-code-running","errorCode":null,"errorMessage":"Blocking security check attempted in code running on the event loop. Make the secured method return an async type, i.e. Uni, Multi or CompletionStage, or use an authentication mechanism that sets the SecurityIdentity in a blocking manner prior to delegating the call","messagePattern":"Blocking security check attempted in code running on the event loop\\. Make the secured method return an async type, i\\.e\\. Uni, Multi or CompletionStage, or use an authentication mechanism that sets the SecurityIdentity in a blocking manner prior to delegating the call","errorType":"exception","errorClass":"BlockingOperationNotAllowedException","httpStatus":null,"severity":"error","filePath":"extensions/security/runtime/src/main/java/io/quarkus/security/runtime/interceptor/SecurityConstrainer.java","lineNumber":68,"sourceCode":"            boolean securityEventsEnabled = ConfigProvider.getConfig().getValue(\"quarkus.security.events.enabled\",\n                    Boolean.class);\n            this.securityEventHelper = new SecurityEventHelper<>(authZSuccessEvent, authZFailureEvent, AUTHORIZATION_SUCCESS,\n                    AUTHORIZATION_FAILURE, beanManager, securityEventsEnabled);\n        } else {\n            // static interceptors are initialized during the static init, therefore we need to initialize the helper lazily\n            this.securityEventHelper = SecurityEventHelper.lazilyOf(authZSuccessEvent, authZFailureEvent,\n                    AUTHORIZATION_SUCCESS, AUTHORIZATION_FAILURE, beanManager);\n        }\n    }\n\n    public void check(Method method, Object[] parameters) {\n        SecurityCheck securityCheck = storage.getSecurityCheck(method);\n        SecurityIdentity identity = null;\n        if (securityCheck != null && !securityCheck.isPermitAll()) {\n            try {\n                identity = securityIdentityAssociation.get().getIdentity();\n            } catch (BlockingOperationNotAllowedException blockingException) {\n                throw new BlockingOperationNotAllowedException(\n                        \"Blocking security check attempted in code running on the event loop. \" +\n                                \"Make the secured method return an async type, i.e. Uni, Multi or CompletionStage, or \" +\n                                \"use an authentication mechanism that sets the SecurityIdentity in a blocking manner \" +\n                                \"prior to delegating the call\",\n                        blockingException);\n            }\n            if (securityEventHelper.fireEventOnFailure()) {\n                try {\n                    securityCheck.apply(identity, method, parameters);\n                } catch (Exception exception) {\n                    fireAuthZFailureEvent(identity, exception, securityCheck, method);\n                    throw exception;\n                }\n            } else {\n                securityCheck.apply(identity, method, parameters);\n            }\n        }\n        if (securityEventHelper.fireEventOnSuccess()) {","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/security/runtime/src/main/java/io/quarkus/security/runtime/interceptor/SecurityConstrainer.java#L50-L86","documentation":"A synchronous (@RolesAllowed/@Authenticated) security check attempted to resolve the current SecurityIdentity by blocking while the request ran on the IO event loop thread, which Quarkus forbids (BlockingOperationNotAllowedException rethrown with guidance). Reactive/RESTEasy-reactive pipelines cannot block the event loop, so authentication that requires blocking must be done before dispatch or the endpoint must be async.","triggerScenarios":"Securing a reactive endpoint (returns Uni/Multi/CompletionStage, or plain object on a reactive execution model) whose identity is not yet resolved at interceptor time and whose auth mechanism would block; calling identity.get() on the event loop in a RESTEasy Reactive app.","commonSituations":"Mixed blocking/reactive setups: JPA-based identity provider called from a reactive endpoint; quarkus-oidc without proactive auth combined with synchronous @RolesAllowed on a reactive resource; after migration from RESTEasy Classic to RESTEasy Reactive.","solutions":["Make the secured method return an async type (Uni, Multi, or CompletionStage) so the check runs on a worker thread","Annotate the class/method with @RunOnVirtualThread or @Blocking so the security check executes on a blocking thread","Configure the authentication mechanism to resolve the SecurityIdentity proactively/blocking before the call (e.g. enable proactive OIDC auth)","Move blocking identity resolution into a non-blocking IdentityProvider"],"exampleFix":"// before\n@RolesAllowed(\"admin\")\npublic String secret() { ... } // event-loop call, blocking identity lookup\n// after\n@RolesAllowed(\"admin\")\npublic Uni<String> secret() { return Uni.createFrom().item(...); }","handlingStrategy":"try-catch","validationCode":"// prefer checking the execution model before relying on blocking identity access\nboolean onEventLoop = Vertx.currentContext() != null;\nif (onEventLoop && requiresBlockingIdentity()) {\n  // switch to async return type or @Blocking / @RunOnVirtualThread\n}","typeGuard":null,"tryCatchPattern":"try {\n  identity = securityIdentityAssociation.get().getIdentity();\n} catch (BlockingOperationNotAllowedException e) {\n  throw new BlockingOperationNotAllowedException(\n    \"Use Uni/Multi/CompletionStage return type or @Blocking/@RunOnVirtualThread\", e);\n}","preventionTips":["Return Uni/Multi/CompletionStage from secured reactive endpoints","Use @Blocking or @RunOnVirtualThread when the identity lookup must block","Enable proactive authentication so the identity is resolved before the interceptor","Test secured reactive endpoints with quarkus-resteasy-reactive to catch this early"],"tags":["security","reactive","event-loop","blocking-operation"],"backgroundTag":"blocking-operation-on-event-loop","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}