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() at websocket.js:368-369 when readyState is CONNECTING (0), i.e. the opening handshake has not completed. Unlike the CLOSING/CLOSED case (which routes to sendAfterClose), CONNECTING is treated as a hard error because the sender is not yet attached to a socket. The guard throws synchronously before any argument reshuffling.
Solutions
- Wait for the 'open' event before pinging: ws.on('open', () => ws.ping()).
- Guard every call: if (ws.readyState === WebSocket.OPEN) ws.ping().
- Move heartbeat logic into an interval started in the 'open' handler and cleared on 'close'.
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 safePing(ws, data) {
if (ws.readyState !== ws.OPEN) return false;
ws.ping(data);
return true;
} Type guard
function isOpen(ws) {
return ws.readyState === WebSocket.OPEN; // 1
} Try / catch
try {
ws.ping(data);
} catch (err) {
if (/CONNECTING/.test(err.message)) {
// defer until open
ws.once('open', () => ws.ping(data));
} else throw err;
} Prevention
- Start heartbeat intervals inside the 'open' handler, not after construction.
- Guard all ping calls with ws.readyState === WebSocket.OPEN.
- Clear heartbeat timers on 'close'/'error'.
When it happens
Trigger: Calling ws.ping(...) immediately after `new WebSocket(url)` before the 'open' event fires; calling ping inside a 'connecting' or constructor-adjacent code path; calling ping from an 'upgrade' event listener (which fires before 'open'). The check at line 368 catches readyState === 0 and throws.
Common situations: Sending a keepalive/heartbeat ping in a function that runs before the connection opens (e.g. right after construction, or in a retry loop); a reconnection manager that pings before re-handshake completes; unit tests that construct a WebSocket and immediately ping without waiting.
Related errors
- The data size must not be greater than 125 bytes
- An invalid or duplicated subprotocol was specified
- First argument must be a valid error code number
- Invalid URL
- Invalid value for parameter
AI-assisted analysis of websockets/ws@c791e707ea (2026-08-06).
Data as JSON: /api/errors/85adf974922b5521.
Report an issue: GitHub.
Appendix: 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 c791e707ea)