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

  1. Wait for the 'open' event before pinging: ws.on('open', () => ws.ping());.
  2. Guard with readyState: if (ws.readyState === WebSocket.OPEN) ws.ping();.
  3. 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

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


AI-assisted analysis of websockets/ws@ae1de54330 (2026-08-03). Data as JSON: /data/errors/85adf974922b5521.json. Report an issue: GitHub.