{"record":{"id":"cf35a3f9f452b733","repo":"karatelabs/karate","slug":"connection-closed","errorCode":"CONNECTION_CLOSED","errorMessage":"websocket is not open","messagePattern":"websocket is not open","errorType":"error_code","errorClass":"WsException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/http/WsClient.java","lineNumber":271,"sourceCode":"    }\n\n    public String getNegotiatedSubprotocol() {\n        return negotiatedSubprotocol;\n    }\n\n    // Sending frames\n\n    public void send(String text) {\n        send(WsFrame.text(text));\n    }\n\n    public void send(byte[] binary) {\n        send(WsFrame.binary(binary));\n    }\n\n    public void send(WsFrame frame) {\n        if (!isOpen()) {\n            throw new WsException(WsException.Type.CONNECTION_CLOSED, \"websocket is not open\");\n        }\n        WebSocketFrame wsFrame = toNettyFrame(frame);\n        channel.writeAndFlush(wsFrame).addListener((ChannelFutureListener) future -> {\n            if (!future.isSuccess()) {\n                logger.error(\"send failed: {}\", future.cause().getMessage());\n            }\n        });\n    }\n\n    public CompletableFuture<Void> sendAsync(WsFrame frame) {\n        if (!isOpen()) {\n            return CompletableFuture.failedFuture(\n                    new WsException(WsException.Type.CONNECTION_CLOSED, \"websocket is not open\"));\n        }\n        CompletableFuture<Void> future = new CompletableFuture<>();\n        WebSocketFrame wsFrame = toNettyFrame(frame);\n        channel.writeAndFlush(wsFrame).addListener((ChannelFutureListener) channelFuture -> {\n            if (channelFuture.isSuccess()) {","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/WsClient.java#L253-L289","documentation":"WsClient.send(WsFrame) first checks isOpen() and throws a WsException of type CONNECTION_CLOSED if the underlying Netty channel is not active. The library refuses to send on a dead/closed connection rather than silently queueing or failing asynchronously. Send failures that occur after this check are only logged, not thrown.","triggerScenarios":"Calling send(String), send(byte[]) or send(WsFrame) after the WebSocket was closed, before connect() completed, or after the server dropped the connection.","commonSituations":"Sending immediately after connect() without waiting for the open event; server-side timeout/close mid-session; forgetting to reconnect after an error listener fired; race between close and send in concurrent code.","solutions":["Check client.isOpen() before each send, or gate sends on the connection-opened callback","Re-establish the connection (call connect()) when the close/error listener fires before sending again","Wrap sends in a catch for WsException and reconnect-and-retry the send","Review server-side idle/close timeouts and send keep-alive/ping frames"],"exampleFix":"// before\nclient.send(\"hello\"); // may throw if closed\n// after\nif (!client.isOpen()) { client.connect(url); awaitOpen(client); }\ntry { client.send(\"hello\"); } catch (WsException e) { reconnectAndResend(client, \"hello\"); }","handlingStrategy":"validation","validationCode":"if (!client.isOpen()) { client.connect(url); awaitOpen(client); }","typeGuard":"boolean canSend = client != null && client.isOpen();","tryCatchPattern":"try { client.send(frame); } catch (WsException e) { if (e.getType() == WsException.Type.CONNECTION_CLOSED) { reconnect(client); client.send(frame); } }","preventionTips":["Gate sends on the connection-open callback, not immediately after connect()","Handle close/error listeners by triggering reconnect before further sends","Add keep-alive/ping to detect dead connections early","Avoid sending concurrently with close()"],"tags":["websocket","connection-closed","network"],"backgroundTag":"invalid-state-transition","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}