{"record":{"id":"0a361b6595a9c105","repo":"quarkusio/quarkus","slug":"no-current-vertx-context-found-0a361b","errorCode":null,"errorMessage":"No current Vertx context found","messagePattern":"No current Vertx context found","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/reactive-transactions/runtime/src/main/java/io/quarkus/reactive/transaction/runtime/TransactionalInterceptorBase.java","lineNumber":305,"sourceCode":"                    \"Calling a method annotated with @Transactional from a method annotated with @ReactiveTransactional is not supported. \"\n                            + \"Use either @Transactional or @WithSessionOnDemand/@WithSession/@WithTransaction, \"\n                            + \"but not both, throughout your whole application.\");\n        }\n    }\n\n    /**\n     *\n     * @return the current vertx duplicated context\n     * @throws IllegalStateException If no vertx context is found or is not a safe context as mandated by the\n     *         {@link VertxContextSafetyToggle}\n     */\n    private static Context vertxContext() {\n        Context context = Vertx.currentContext();\n        if (context != null) {\n            VertxContextSafetyToggle.validateContextIfExists(ERROR_MSG, ERROR_MSG);\n            return context;\n        } else {\n            throw new IllegalStateException(\"No current Vertx context found\");\n        }\n    }\n\n    // Default impl fails .REQUIRED overrides it\n    protected void validateTransactionalType(InvocationContext context) {\n        Transactional transactional = context.getMethod().getAnnotation(Transactional.class);\n        if (transactional != null && transactional.value() != Transactional.TxType.REQUIRED) {\n            throw new UnsupportedOperationException(\n                    \"@Transactional on Reactive methods supports only Transactional.TxType.REQUIRED\");\n        }\n    }\n\n    /**\n     * <p>\n     * Looking for the {@link Transactional} annotation first on the method,\n     * second on the class.\n     * <p>\n     * Method handles CDI types to cover cases where extensions are used. In","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/reactive-transactions/runtime/src/main/java/io/quarkus/reactive/transaction/runtime/TransactionalInterceptorBase.java#L287-L323","documentation":"The interceptor needs the current Vert.x duplicated Context to store transaction/session state safely. If Vertx.currentContext() returns null, the code is not running on a Vert.x (event-loop/virtual-thread) context, so it throws IllegalStateException(\"No current Vertx context found\").","triggerScenarios":"Invoking a @Transactional/@ReactiveTransactional reactive method from a plain thread (e.g. CompletableFuture.runAsync, custom executor, scheduled task, or main thread) that has no Vertx duplicated context.","commonSituations":"Calling reactive transactional beans from @Scheduled tasks, tests without QuarkusVertxTest support, or manually spawned threads; blocking the chain and resuming on a non-Vertx thread.","solutions":["Run the call on a Vertx-managed thread, e.g. wrap in uni.emitOn(quarkus executor) or invoke from an event-loop/RESTEasy Reactive endpoint.","Use Quarkus's managed executors (@Inject ManagedExecutor / Vertx.getOrCreate(context)) so the duplicated context is propagated.","For scheduled/background work, use QuarkusScheduler (@Scheduled with reactive support) which preserves Vertx contexts."],"exampleFix":"// before\nCompletableFuture.runAsync(() -> service.save(item)); // no Vertx context\n// after\nUni.createFrom().item(item)\n   .emitOn(Infrastructure.getDefaultWorkerPool())\n   .chain(i -> service.save(i)) // interceptor runs with propagated duplicated context","handlingStrategy":"validation","validationCode":"// guard before invoking a reactive transactional method off the Vertx event loop\nif (Vertx.currentContext() == null)\n    throw new IllegalStateException(\"Not on a Vertx context; run via event loop or emitOn/ManagedExecutor\");","typeGuard":null,"tryCatchPattern":"try {\n    return service.save(item);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"No current Vertx context\")) {\n        log.warn(\"Called off Vertx context; rerun on Vertx-managed thread\");\n    }\n    throw e;\n}","preventionTips":["Don't call reactive @Transactional methods from plain threads/executors","Use Quarkus @Scheduled or the Vert.x-managed scheduler for background jobs","Propagate duplicated contexts with ManagedExecutor instead of CompletableFuture.runAsync","Add a startup sanity test invoking reactive tx beans"],"tags":["quarkus","reactive-transactions","vertx","context"],"backgroundTag":"missing-vertx-context","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"}