quarkusio/quarkus · error · RuntimeException

Suspendable rest client method{jandexMethod} is present on c

Error message

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.

What it means

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.

Source

Thrown at extensions/resteasy-reactive/rest-client-jaxrs/deployment/src/main/java/io/quarkus/jaxrs/client/reactive/deployment/JaxrsClientReactiveProcessor.java:2652

                    }
                }
            } else {
                genericReturnType = createGenericTypeFromParameterizedType(methodCreator, paramType);
            }
        }
        Integer continuationIndex = null;
        //TODO: there should be an SPI for this
        if (returnCategory == ReturnCategory.BLOCKING) {
            List<Type> parameters = jandexMethod.parameterTypes();
            if (!parameters.isEmpty()) {
                Type lastParamType = parameters.get(parameters.size() - 1);
                if (lastParamType.name().equals(CONTINUATION)) {
                    continuationIndex = parameters.size() - 1;
                    returnCategory = ReturnCategory.COROUTINE;

                    if (!QuarkusClassLoader.isClassPresentAtRuntime(UNI_KT.toString())) {
                        //TODO: make this automatic somehow
                        throw new RuntimeException("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.");
                    }

                    //we infer the return type from the param type of the continuation
                    Type type = lastParamType.asParameterizedType().arguments().get(0);
                    for (;;) {
                        if (type.kind() == PARAMETERIZED_TYPE) {
                            genericReturnType = createGenericTypeFromParameterizedType(methodCreator,
                                    type.asParameterizedType());
                            break;
                        } else if (type.kind() == Type.Kind.WILDCARD_TYPE) {
                            if (type.asWildcardType().extendsBound().name().equals(OBJECT)) {
                                type = type.asWildcardType().superBound();
                            } else {
                                type = type.asWildcardType().extendsBound();
                            }
                        } else {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add the dependency io.smallrye.reactive:mutiny-kotlin to the application (runtime scope)
  2. Check exclusions in the Maven/Gradle config — ensure mutiny-kotlin isn't excluded transitively
  3. Remove the suspend modifier and return Uni<T> instead if Kotlin coroutines support isn't wanted

Example fix

// before (build.gradle.kts)
implementation("io.quarkus:quarkus-rest-client-reactive")
// after
implementation("io.quarkus:quarkus-rest-client-reactive")
implementation("io.smallrye.reactive:mutiny-kotlin")
Defensive patterns

Strategy: validation

Validate before calling

// Before declaring suspend client methods, ensure the dependency is present:
try {
    Class.forName("io.smallrye.mutiny.coroutines.UniKt");
} catch (ClassNotFoundException e) {
    throw new IllegalStateException(
        "Add io.smallrye.reactive:mutiny-kotlin to use suspend REST client methods", e);
}

Try / catch

try {
    val client = QuarkusRestClientBuilder.newBuilder().build(MyClient::class.java)
} catch (e: RuntimeException) {
    if (e.message?.contains("mutiny-kotlin") == true) {
        error("Missing io.smallrye.reactive:mutiny-kotlin dependency: ${e.message}")
    } else throw e
}

Prevention

When it happens

Trigger: Defining `suspend fun getData(): Foo` in a Kotlin @RegisterRestClient interface without io.smallrye.reactive:mutiny-kotlin on the runtime classpath.

Common situations: Adding a suspend method to an existing Quarkus Kotlin REST client and forgetting the extra dependency; dependency exclusions removing mutiny-kotlin transitively.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/7d2a245caeb1197a. Report an issue: GitHub.