{"record":{"id":"7d2a245caeb1197a","repo":"quarkusio/quarkus","slug":"suspendable-rest-client-method-jandexmethod-is-pr","errorCode":null,"errorMessage":"Suspendable rest client method{jandexMethod} is present on class {jandexMethod.declaringClass} however io.smallrye.reactive:mutiny-kotlin is not detected. Please add a dependency on this artifact.","messagePattern":"Suspendable rest client method(.+?) is present on class (.+?) however io\\.smallrye\\.reactive:mutiny-kotlin is not detected\\. Please add a dependency on this artifact\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java","lineNumber":2652,"sourceCode":"                    }\n                }\n            } else {\n                genericReturnType = createGenericTypeFromParameterizedType(methodCreator, paramType);\n            }\n        }\n        Integer continuationIndex = null;\n        //TODO: there should be an SPI for this\n        if (returnCategory == ReturnCategory.BLOCKING) {\n            List<Type> parameters = jandexMethod.parameterTypes();\n            if (!parameters.isEmpty()) {\n                Type lastParamType = parameters.get(parameters.size() - 1);\n                if (lastParamType.name().equals(CONTINUATION)) {\n                    continuationIndex = parameters.size() - 1;\n                    returnCategory = ReturnCategory.COROUTINE;\n\n                    if (!QuarkusClassLoader.isClassPresentAtRuntime(UNI_KT.toString())) {\n                        //TODO: make this automatic somehow\n                        throw new RuntimeException(\"Suspendable rest client method\" + jandexMethod + \" is present on class \"\n                                + jandexMethod.declaringClass()\n                                + \" however io.smallrye.reactive:mutiny-kotlin is not detected. Please add a dependency on this artifact.\");\n                    }\n\n                    //we infer the return type from the param type of the continuation\n                    Type type = lastParamType.asParameterizedType().arguments().get(0);\n                    for (;;) {\n                        if (type.kind() == PARAMETERIZED_TYPE) {\n                            genericReturnType = createGenericTypeFromParameterizedType(methodCreator,\n                                    type.asParameterizedType());\n                            break;\n                        } else if (type.kind() == Type.Kind.WILDCARD_TYPE) {\n                            if (type.asWildcardType().extendsBound().name().equals(OBJECT)) {\n                                type = type.asWildcardType().superBound();\n                            } else {\n                                type = type.asWildcardType().extendsBound();\n                            }\n                        } else {","sourceCodeStart":2634,"sourceCodeEnd":2670,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java#L2634-L2670","documentation":"A REST client interface method is a Kotlin suspend function (its last parameter is a Continuation), which requires the mutiny-kotlin bridge at runtime to convert coroutines to Mutiny. The runtime class UnKt is not present, so build-time generation refuses to continue rather than fail at call time.","triggerScenarios":"Defining `suspend fun getData(): Foo` in a Kotlin @RegisterRestClient interface without io.smallrye.reactive:mutiny-kotlin on the runtime classpath.","commonSituations":"Adding a suspend method to an existing Quarkus Kotlin REST client and forgetting the extra dependency; dependency exclusions removing mutiny-kotlin transitively.","solutions":["Add the dependency io.smallrye.reactive:mutiny-kotlin to the application (runtime scope)","Check exclusions in the Maven/Gradle config — ensure mutiny-kotlin isn't excluded transitively","Remove the suspend modifier and return Uni<T> instead if Kotlin coroutines support isn't wanted"],"exampleFix":"// before (build.gradle.kts)\nimplementation(\"io.quarkus:quarkus-rest-client-reactive\")\n// after\nimplementation(\"io.quarkus:quarkus-rest-client-reactive\")\nimplementation(\"io.smallrye.reactive:mutiny-kotlin\")","handlingStrategy":"validation","validationCode":"// Before declaring suspend client methods, ensure the dependency is present:\ntry {\n    Class.forName(\"io.smallrye.mutiny.coroutines.UniKt\");\n} catch (ClassNotFoundException e) {\n    throw new IllegalStateException(\n        \"Add io.smallrye.reactive:mutiny-kotlin to use suspend REST client methods\", e);\n}","typeGuard":null,"tryCatchPattern":"try {\n    val client = QuarkusRestClientBuilder.newBuilder().build(MyClient::class.java)\n} catch (e: RuntimeException) {\n    if (e.message?.contains(\"mutiny-kotlin\") == true) {\n        error(\"Missing io.smallrye.reactive:mutiny-kotlin dependency: ${e.message}\")\n    } else throw e\n}","preventionTips":["Add io.smallrye.reactive:mutiny-kotlin whenever quarkus-kotlin and REST clients are combined","Check that exclusions don't strip mutiny-kotlin transitively","Prefer returning Uni<T> from Kotlin clients if coroutine support isn't required"],"tags":["quarkus","rest-client","kotlin","coroutines","missing-dependency"],"backgroundTag":"missing-mutiny-kotlin-dependency","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}