{"record":{"id":"dd84be1be87a0d68","repo":"quarkusio/quarkus","slug":"transactional-on-reactive-methods-supports-only-t","errorCode":null,"errorMessage":"@Transactional on Reactive methods supports only Transactional.TxType.REQUIRED","messagePattern":"@Transactional on Reactive methods supports only Transactional\\.TxType\\.REQUIRED","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"extensions/reactive-transactions/runtime/src/main/java/io/quarkus/reactive/transaction/runtime/TransactionalInterceptorBase.java","lineNumber":313,"sourceCode":"     * @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\n     * case of EE container uses reflection.\n     *\n     * @param context invocation context of the interceptor\n     * @return instance of {@link Transactional} annotation or null\n     */\n    private Transactional getTransactionalAnnotation(InvocationContext context) {\n        Set<Annotation> bindings = InterceptorBindings.getInterceptorBindings(context);\n        for (Annotation binding : bindings) {","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/reactive-transactions/runtime/src/main/java/io/quarkus/reactive/transaction/runtime/TransactionalInterceptorBase.java#L295-L331","documentation":"The base reactive transactional interceptor only supports TxType.REQUIRED for @Transactional-annotated reactive methods; other tx types (REQUIRES_NEW, MANDATORY, SUPPORTS, NOT_SUPPORTED, NEVER) have no reactive implementation and throw UnsupportedOperationException. Subclasses (e.g. the JTA reactive interceptor) may override this check.","triggerScenarios":"Annotating a Uni-returning reactive method with @Transactional(value = Transactional.TxType.REQUIRES_NEW) (or any type other than REQUIRED) and having the base interceptor validate it.","commonSituations":"Copy-pasting blocking JTA tx types into reactive services; trying REQUIRES_NEW for nested independent transactions in reactive code.","solutions":["Use @Transactional (default REQUIRED) on the reactive method.","If an independent new transaction is truly needed, split the operation into a separate bean method and call it so the outer transaction isn't active, or use @WithTransaction on the sub-operation.","If using the Narayana STJ integration, use @ReactiveTransactional which supports the required semantics."],"exampleFix":"// before\n@Transactional(Transaction.TxType.REQUIRES_NEW)\npublic Uni<Void> audit(Event e) { ... }\n// after\n@Transactional\npublic Uni<Void> audit(Event e) { ... }","handlingStrategy":"validation","validationCode":"Transactional t = method.getAnnotation(Transactional.class);\nif (t != null && t.value() != Transactional.TxType.REQUIRED)\n    throw new IllegalArgumentException(\"Reactive @Transactional supports only REQUIRED, found \" + t.value());","typeGuard":null,"tryCatchPattern":"try {\n    return service.audit(e);\n} catch (UnsupportedOperationException ex) {\n    log.error(\"Use TxType.REQUIRED on reactive methods: {}\", ex.getMessage());\n    throw ex;\n}","preventionTips":["Only use plain @Transactional (REQUIRED) on Uni-returning methods","Refactor REQUIRES_NEW needs into separate bean methods","Review annotation values during code review of reactive services","Prefer @ReactiveTransactional semantics from Quarkus docs"],"tags":["quarkus","reactive-transactions","txtype"],"backgroundTag":"unsupported-tx-type","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"}