{"record":{"id":"577f33f09a7434d9","repo":"quarkusio/quarkus","slug":"unable-to-obtain-the-connection-from-the-vert-x-du","errorCode":null,"errorMessage":"Unable to obtain the connection from the Vert.x duplicated context","messagePattern":"Unable to obtain the connection from the Vert\\.x duplicated context","errorType":"exception","errorClass":"WebSocketClientException","httpStatus":null,"severity":"error","filePath":"extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketClientRecorder.java","lineNumber":28,"sourceCode":"import io.vertx.core.Context;\nimport io.vertx.core.Vertx;\n\n@Recorder\npublic class WebSocketClientRecorder {\n\n    public Supplier<Object> connectionSupplier() {\n        return new Supplier<Object>() {\n\n            @Override\n            public Object get() {\n                Context context = Vertx.currentContext();\n                if (context != null && VertxContext.isDuplicatedContext(context)) {\n                    Object connection = ContextSupport.WebSocketContextLocalsProvider.WEB_SOCKET_CONN_LOCAL.get(context);\n                    if (connection != null) {\n                        return connection;\n                    }\n                }\n                throw new WebSocketClientException(\"Unable to obtain the connection from the Vert.x duplicated context\");\n            }\n        };\n    }\n\n    public Supplier<Object> createContext(Map<String, ClientEndpoint> endpointMap) {\n        return new Supplier<Object>() {\n            @Override\n            public Object get() {\n                return new ClientEndpointsContext() {\n\n                    @Override\n                    public ClientEndpoint endpoint(String endpointClass) {\n                        return endpointMap.get(endpointClass);\n                    }\n\n                };\n            }\n        };","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/websockets-next/runtime/src/main/java/io/quarkus/websockets/next/runtime/WebSocketClientRecorder.java#L10-L46","documentation":"Thrown by the WebSocket client connection supplier when it fails to retrieve the current WebSocket connection from the active Vert.x duplicated context. The connection is stored in a context local (WEB_SOCKET_CONN_LOCAL) which is only populated while executing on the duplicated context associated with an established client connection. If code runs on a plain context, a different context, or the connection local was never set, the lookup returns null and this error is thrown.","triggerScenarios":"Calling WebSocketConnection/endpoint APIs that resolve the current connection via the injected Supplier (connectionContext() style lookup) from outside the duplicated context of an active client connection — e.g. from a worker thread spawned manually, a scheduled task, a @PostConstruct, or before the connection is established.","commonSituations":"Delegating endpoint callbacks to a custom executor without capturing/switching back to the original duplicated context; calling connection lookup lazily after the endpoint lifecycle ended; using the client connection supplier from unrelated code paths.","solutions":["Ensure the code runs on the Vert.x duplicated context captured for the connection (e.g. context.runOnContext or VertxContextSupport.executeBlocking-style helpers)","Do not manually switch thread/context inside endpoint callbacks; let websockets-next propagate the duplicated context","Verify the connection is actually established before invoking APIs that resolve the current connection","If you must hop threads, capture the duplicated context (Vertx.currentContext()) up front and restore it before the lookup"],"exampleFix":"// before\nExecutors.newSingleThreadExecutor().submit(() -> connection.send(...));\n// after\ncontext.runOnContext(v -> connection.send(...));","handlingStrategy":"try-catch","validationCode":"io.vertx.core.Context ctx = Vertx.currentContext();\nboolean ok = ctx != null && io.quarkus.websockets.next.runtime.VertxContext.isDuplicatedContext(ctx);","typeGuard":"static boolean hasConnectionInContext(io.vertx.core.Context ctx) {\n    return ctx != null && io.quarkus.websockets.next.runtime.VertxContext.isDuplicatedContext(ctx);\n}","tryCatchPattern":"try {\n    connection.send(msg);\n} catch (WebSocketClientException e) {\n    // not on the connection's duplicated context; re-dispatch\n    capturedContext.runOnContext(v -> connection.send(msg));\n}","preventionTips":["Never spawn raw threads inside WebSocket endpoint callbacks","Use Quarkus context-aware executors for async work","Capture the duplicated context early and reuse it for delayed calls","Keep connection API calls within the endpoint lifecycle"],"tags":["websockets","vertx","context-local","threading"],"backgroundTag":"missing-duplicated-context","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"}