websockets/ws · error · Error
WebSocket is not open: readyState 0 (CONNECTING)
Error message
WebSocket is not open: readyState 0 (CONNECTING)
What it means
Thrown by WebSocket.prototype.ping() (lib/websocket.js:367-370) when called while readyState is CONNECTING (0), i.e. before the opening handshake has completed. The underlying Sender has no usable socket state yet and the library refuses to queue a control frame for a connection that may never open. Note: if readyState is CLOSING or CLOSED, ping() does NOT throw but silently calls sendAfterClose() and reports the error via the callback; the throw is specific to the CONNECTING state.
Source
Thrown at lib/websocket.js:369
) {
return;
}
this._paused = true;
this._socket.pause();
}
/**
* Send a ping.
*
* @param {*} [data] The data to send
* @param {Boolean} [mask] Indicates whether or not to mask `data`
* @param {Function} [cb] Callback which is executed when the ping is sent
* @public
*/
ping(data, mask, cb) {
if (this.readyState === WebSocket.CONNECTING) {
throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
}
if (typeof data === 'function') {
cb = data;
data = mask = undefined;
} else if (typeof mask === 'function') {
cb = mask;
mask = undefined;
}
if (typeof data === 'number') data = data.toString();
if (this.readyState !== WebSocket.OPEN) {
sendAfterClose(this, data, cb);
return;
}
if (mask === undefined) mask = !this._isServer;View on GitHub (pinned to ae1de54330)
Solutions
- Wait for the 'open' event before pinging: ws.on('open', () => ws.ping());.
- Guard with readyState: if (ws.readyState === WebSocket.OPEN) ws.ping();.
- Use the callback form after open so post-close failures are reported via cb instead of throwing.
Example fix
// before
const ws = new WebSocket(url);
ws.ping(); // throws, still CONNECTING
// after
const ws = new WebSocket(url);
ws.on('open', () => ws.ping()); Defensive patterns
Strategy: validation
Validate before calling
function pingWhenOpen(ws, data, cb) {
if (ws.readyState !== ws.OPEN) return; // or queue and flush on 'open'
ws.ping(data, cb);
} Type guard
function isOpen(ws) {
return ws.readyState === ws.OPEN; // 1
} Try / catch
try {
ws.ping(data, cb);
} catch (err) {
if (/CONNECTING/.test(err.message)) {
ws.once('open', () => ws.ping(data, cb));
} else {
throw err;
}
} Prevention
- Send pings only after the 'open' event.
- Guard with ws.readyState === WebSocket.OPEN.
- Drive heartbeats from a timer started in the 'open' handler.
When it happens
Trigger: Calling ws.ping(...) immediately after `new WebSocket(url)` synchronously, or inside a non-'open' handler, before the 'open' event fires. The check at line 368 throws synchronously.
Common situations: Sending an initial heartbeat before the connection is established; calling ping in the constructor or in a module-init path; reusing a WebSocket reference across reconnect attempts where the new socket is still CONNECTING.
Related errors
- Unsupported protocol version: ${opts.protocolVersion} (suppo
- Invalid URL: ${address}
- An invalid or duplicated subprotocol was specified
- ws does not work in the browser. Browser clients must use th
- Unexpected character at index ${i}
AI-assisted analysis of websockets/ws@ae1de54330 (2026-08-03).
Data as JSON: /data/errors/85adf974922b5521.json.
Report an issue: GitHub.