slackapi / slackapi/node-slack-sdk

socket-mode: "Received unexpected ping diagnostics message format" WARN for pings on other libraries' WebSockets in the same process

Open Beginner friendly
#2,743 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
3.4k
Forks
688
Avg merge
15h 31m
Merged PRs (30d)
27

Description

Package

@slack/socket-mode

SDK Version

@slack/socket-mode@3.0.1 (also 3.0.0), undici@7.29.1 as the peer dependency

Node.js Version

v22.12.0 (bundled undici 6.21.0) and v24.21.0 (bundled undici 7.29.1 — the same version as the npm peer, and it still reproduces)

Operating System

macOS 26.6.2

Steps to Reproduce

SlackWebSocket subscribes to undici's undici:websocket:ping / undici:websocket:pong diagnostics channels. Those channels are process-global: every undici WebSocket publishes to them, including Node's built-in global WebSocket, which is a separate copy of undici from the one @slack/socket-mode imports — even when the two are the same version.

pingHandler / pongHandler run isPingPongMessage(message) first, and that guard does message.websocket instanceof WebSocket against the npm undici import. A frame received on any socket that was opened with the global WebSocket fails that instanceof, so the handler logs a WARN before it gets to the message.websocket !== this.websocket check that would have ignored it silently:

https://github.com/slackapi/node-slack-sdk/blob/main/packages/socket-mode/src/SlackWebSocket.ts#L21-L32
https://github.com/slackapi/node-slack-sdk/blob/main/packages/socket-mode/src/SlackWebSocket.ts#L197-L204

So any other library in the process that opens a WebSocket with the global WebSocket and gets pinged by its server produces one [WARN] Received unexpected ping diagnostics message format per ping. In our case that was a Nostr relay client (nostr-tools, which uses the global WebSocket) whose relay sends a keepalive ping every 30s — so a perfectly healthy Slack connection logged that WARN every 30s for as long as it was up. Slack's own pings pass the check and never warn.

Standalone reproduction, no Slack account needed — a local stand-in for apps.connections.open and the Socket Mode server:

mkdir repro && cd repro && npm init -y >/dev/null
npm i @slack/socket-mode@3.0.1 undici@7 ws
node repro.mjs
// repro.mjs
import { createServer } from "node:http";
import { once } from "node:events";
import { SocketModeClient } from "@slack/socket-mode";
import { WebSocketServer } from "ws";

// Enough of Slack for socket-mode to come up: apps.connections.open hands out the
// WebSocket URL, and every connection is greeted with `hello`. The server pings a
// connection only when asked to.
const sockets = [];
const wss = new WebSocketServer({ host: "127.0.0.1", port: 0 });
wss.on("connection", (socket) => {
  sockets.push(socket);
  socket.send(JSON.stringify({ type: "hello" }));
});
await once(wss, "listening");
const wsUrl = `ws://127.0.0.1:${wss.address().port}/`;

const http = createServer((_req, res) => {
  res.setHeader("content-type", "application/json");
  res.end(JSON.stringify({ ok: true, url: wsUrl }));
});
http.listen(0, "127.0.0.1");
await once(http, "listening");

const client = new SocketModeClient({
  appToken: "xapp-test",
  clientOptions: { slackApiUrl: `http://127.0.0.1:${http.address().port}/api/` },
  autoReconnectEnabled: false,
});
await client.start();
console.log("socket-mode connected");

// Some other library in the same process opens a WebSocket with Node's built-in
// global `WebSocket` (Node's bundled undici — a different copy from the npm one).
const other = new WebSocket(wsUrl);
await once(other, "open");

// The server pings *that* socket, not Slack's. socket-mode warns.
const pong = once(sockets[1], "pong");
sockets[1].ping();
await pong;

// Slack's own socket is pinged: no warning.
const pong2 = once(sockets[0], "pong");
sockets[0].ping();
await pong2;

other.close();
await client.disconnect();
wss.close();
http.close();
Expected Result

No log output. A ping or pong frame for a socket that is not SlackWebSocket's own is not about Slack, and should be ignored the same way a frame from a second SocketModeClient's socket already is.

Actual Result
socket-mode connected
[WARN]  socket-mode:SlackWebSocket:1 Received unexpected ping diagnostics message format

One WARN per ping frame received on the other socket; nothing for the ping on Slack's own socket. Same output on Node 22.12.0 and 24.21.0.

Suggested fix

Check identity before shape: return early when message?.websocket !== this.websocket, then validate payload. A frame that is not for this socket is expected on a shared channel, so it should not be logged at all (or at most at debug). The pongHandler has the same guard and the same problem.

Happy to open a PR if that shape is acceptable.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/socket-mode/src/SlackWebSocket.ts, especially the pingHandler and pongHandler locations linked in the issue, and run the standalone reproduction to observe the warning. Update the handling so frames from other sockets are ignored before validation; done means the reproduction produces no warning for the other WebSocket while Slack's socket continues to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
nodejs, typescript
Domain
networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.