{"record":{"id":"650b6dfca732ca88","repo":"quarkusio/quarkus","slug":"cannot-specify-both-an-exception-handler-and-suspe","errorCode":null,"errorMessage":"Cannot specify both an exception handler and SUSPEND_EXISTING","messagePattern":"Cannot specify both an exception handler and SUSPEND_EXISTING","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/QuarkusTransactionImpl.java","lineNumber":42,"sourceCode":"    private static UserTransaction cachedUserTransaction;\n\n    public static <T> T call(RunOptionsBase options, Callable<T> task) {\n        switch (options.semantics) {\n            case REQUIRE_NEW:\n                return callRequireNew(options, task);\n            case DISALLOW_EXISTING:\n                return callDisallowExisting(options, task);\n            case JOIN_EXISTING:\n                return callJoinExisting(options, task);\n            case SUSPEND_EXISTING:\n                return callSuspendExisting(options, task);\n        }\n        throw new IllegalArgumentException(\"Unknown semantics\");\n    }\n\n    private static <T> T callSuspendExisting(RunOptionsBase options, Callable<T> task) {\n        if (options.exceptionHandler != null) {\n            throw new IllegalStateException(\"Cannot specify both an exception handler and SUSPEND_EXISTING\");\n        }\n        TransactionManager transactionManager = getTransactionManager();\n        Transaction transaction = null;\n        try {\n            if (isTransactionActive()) {\n                transaction = transactionManager.suspend();\n            }\n            T result = task.call();\n            if (transaction != null) {\n                try {\n                    transactionManager.resume(transaction);\n                    transaction = null;\n                } catch (Exception e) {\n                    throw new QuarkusTransactionException(e);\n                }\n            }\n            return result;\n        } catch (Exception e) {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/narayana-jta/runtime/src/main/java/io/quarkus/narayana/jta/QuarkusTransactionImpl.java#L24-L60","documentation":"callSuspendExisting (used for TransactionSemantics.SUSPEND_EXISTING) throws IllegalStateException when both an exception handler and SUSPEND_EXISTING semantics are configured. Suspending the existing transaction means exceptions propagate to manage the outer transaction, which is incompatible with intercepting exceptions via a handler.","triggerScenarios":"Building RunOptions/RunOptionsBase with .exceptionHandler(...) and running via QuarkusTransaction.call/run with TransactionSemantics.SUSPEND_EXISTING.","commonSituations":"Combining a retry/exception-handler option copied from REQUIRED-style options with the SUSPEND_EXISTING semantics; misconfigured programmatic transaction runners.","solutions":["Remove the exceptionHandler when using SUSPEND_EXISTING","Switch semantics to one that supports exception handlers (e.g. REQUIRED/REQUIRES_NEW)","Handle exceptions around the QuarkusTransaction.call yourself instead of via the handler option"],"exampleFix":"// before\nQuarkusTransaction.call(new RunOptions().runOptions().exceptionHandler(handler), TaskSemantics.SUSPEND_EXISTING ...)\n// after\nQuarkusTransaction.call(new RunOptions(), task); // SUSPEND_EXISTING, no handler\n// or handle exceptions outside the call","handlingStrategy":"validation","validationCode":"if (options.exceptionHandler != null && semantics == TransactionSemantics.SUSPEND_EXISTING) {\n    throw new IllegalStateException(\"exceptionHandler cannot be combined with SUSPEND_EXISTING\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    QuarkusTransaction.call(runOptions, task);\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"exception handler and SUSPEND_EXISTING\")) {\n        // retry without the handler\n    } else throw e;\n}","preventionTips":["Never set exceptionHandler with SUSPEND_EXISTING semantics","Read the Javadoc of RunOptionsBase.exceptionHandler for supported semantics","Centralize RunOptions construction in one utility to enforce the rule"],"tags":["narayana","transaction","illegal-state","api-misuse"],"backgroundTag":"incompatible-transaction-options","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"}