quarkusio/quarkus · error · IllegalStateException
No Vertx context found
Error message
No Vertx context found
What it means
CoroutineInvocationHandler.handle requires a Vert.x duplicated/context to build a VertxDispatcher for resuming the coroutine on the right event-loop context. When Vertx.currentContext() returns null (no Vert.x context is active on the current thread), it throws IllegalStateException("No Vertx context found").
Source
Thrown at extensions/resteasy-reactive/rest-kotlin/runtime/src/main/kotlin/org/jboss/resteasy/reactive/server/runtime/kotlin/CoroutineInvocationHandler.kt:34
private val invoker: EndpointInvoker,
private val coroutineScope: CoroutineScope,
) : ServerRestHandler {
private val originalTCCL: ClassLoader = Thread.currentThread().contextClassLoader
override fun handle(requestContext: ResteasyReactiveRequestContext) {
if (requestContext.result != null) {
return
}
if (invoker !is CoroutineEndpointInvoker) {
requestContext.handleException(IllegalStateException("Not a coroutine invoker"), true)
return
}
val requestScope = requestContext.captureCDIRequestScope()
val dispatcher: CoroutineDispatcher =
Vertx.currentContext()?.let { VertxDispatcher(it, requestScope, requestContext) }
?: throw IllegalStateException("No Vertx context found")
logger.trace("Handling request with dispatcher {}", dispatcher)
requestContext.suspend()
val done = AtomicBoolean()
val canceled = AtomicBoolean()
val job =
coroutineScope.launch(context = dispatcher) {
// ensure the proper CL is not lost in dev-mode
Thread.currentThread().contextClassLoader = originalTCCL
try {
val result =
invoker.invokeCoroutine(
requestContext.endpointInstance,
requestContext.parameters,
)
done.set(true)View on GitHub (pinned to e1c734241f)
Solutions
- Ensure the request goes through the standard RESTEasy Reactive HTTP pipeline so Vert.x dispatches it on an event loop
- Do not call suspend endpoint methods directly from worker/blocking threads or plain unit tests
- If using custom threading, keep the Vert.x context attached (use Vertx.getOrCreateContext or run within context.runOnContext)
- Upgrade Quarkus — newer versions handle context propagation more robustly
Example fix
// before (direct call in test)
val result = myResource.get("id")
// after
@Test
fun test() {
given().get("/my-resource").then().statusCode(200)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Guard before invoking coroutine handling
if (io.vertx.core.Vertx.currentContext() == null) {
throw IllegalStateException("suspend endpoint invoked without a Vert.x context")
} Type guard
fun hasVertxContext(): Boolean = io.vertx.core.Vertx.currentContext() != null
Try / catch
try {
handler.handle(requestContext)
} catch (e: IllegalStateException) {
if (e.message?.contains("No Vertx context found") == true) {
// fall back to non-coroutine dispatch or fail the request with 500
}
throw e
} Prevention
- Always serve suspend endpoints via the HTTP pipeline, not direct calls
- Avoid @Blocking on suspend endpoints
- Use RestAssured/HTTP client in tests rather than invoking resource methods directly
When it happens
Trigger: Invoking a Kotlin suspend endpoint outside the normal Vert.x event-loop dispatch path — e.g. from a thread that was never attached to a Vert.x context (custom thread pool, direct bean method call, blocking pipeline stage).
Common situations: Calling resource methods directly in tests without the HTTP layer; running the endpoint through custom executors; misconfigured threading extensions that move the request off Vert.x contexts before the coroutine handler runs.
Related errors
- No Vertx context found
- No Vertx context found
- No Vertx context found
- Suspendable @Blocking methods are not supported yet: %s.%s
- Not a coroutine invoker
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ece8f95a806d4cb2.
Report an issue: GitHub.