quarkusio/quarkus · error · IllegalStateException

No Vertx context found

Error message

No Vertx context found

What it means

CoroutineInvoker.inNewCoroutine launches the endpoint callback on a coroutine dispatched by the current Vert.x context. If Vertx.currentContext() returns null (the code is not running on a Vert.x/duplicated context), it throws IllegalStateException 'No Vertx context found'.

Source

Thrown at extensions/websockets-next/kotlin/src/main/kotlin/io/quarkus/websockets/next/runtime/kotlin/CoroutineInvoker.kt:22

import io.smallrye.mutiny.Uni
import io.smallrye.mutiny.coroutines.asUni
import io.vertx.core.Vertx
import jakarta.enterprise.invoke.Invoker
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async

object CoroutineInvoker {
    @JvmStatic
    @OptIn(ExperimentalCoroutinesApi::class)
    fun <T, U> inNewCoroutine(instance: T, arguments: Array<Any?>, invoker: Invoker<T, U>): Uni<U> {
        val coroutineScope = Arc.container().instance(ApplicationCoroutineScope::class.java).get()
        val dispatcher: CoroutineDispatcher =
            Vertx.currentContext()?.let(::VertxDispatcher)
                ?: throw IllegalStateException("No Vertx context found")

        return coroutineScope
            .async<U>(context = dispatcher) {
                suspendCoroutine { continuation ->
                    arguments[arguments.size - 1] = continuation
                    try {
                        continuation.resume(invoker.invoke(instance, arguments))
                    } catch (e: Exception) {
                        continuation.resumeWithException(e)
                    }
                }
            }
            .asUni()
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Ensure the callback is invoked on a Vert.x-managed thread (Vertx.getOrCreateContext context exists)
  2. Do not call endpoint callbacks directly from custom thread pools; route through the WebSockets Next invocation machinery
  3. In tests, use @RunOnVertxContext or Quarkus test harness so a Vertx context is active

Example fix

// before
executor.submit { endpoint.onMessage(msg) } // no Vertx context
// after
vertx.runOnContext { endpoint.onMessage(msg) } // or rely on WebSockets Next dispatch
Defensive patterns

Strategy: try-catch

Validate before calling

val ctx = Vertx.currentContext()
requireNotNull(ctx) { "inNewCoroutine must run on a Vert.x context" }

Type guard

fun onVertxContext(): Boolean = Vertx.currentContext() != null

Try / catch

try {
    CoroutineInvoker.inNewCoroutine(instance, args, invoker)
} catch (e: IllegalStateException) {
    // not on a Vert.x thread; reroute via vertx.runOnContext { ... }
}

Prevention

When it happens

Trigger: Invoking a Kotlin suspend WebSockets Next callback from a thread that is not a Vert.x worker/event-loop thread, e.g. from a plain executor, a @Blocking method on a platform thread outside the Vert.x context, or during tests without an active Vertx context.

Common situations: Calling the endpoint method directly from a scheduler thread or unit test; custom threading that breaks the Vert.x context propagation chain.

Related errors


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