Skip to content

Slack Socket Mode: event loop starvation causes pong timeouts and silent message loss #58519

Description

@jrex-jooni

Problem

Slack Socket Mode WebSocket pong responses are missed when the Node.js event loop is busy processing agent turns. We empirically observe 4+ consecutive pong timeouts (5000ms deadline) during heavy turns, which causes Slack to drop the WebSocket connection. Messages sent by the gateway during or just after a dead socket window are silently lost — the gateway logs a successful delivery, but Slack never receives it.

What we observe

  • Environment: OpenClaw 2026.3.28, single gateway process
  • Pattern: Heavy agent turns (tool calls, sub-agent orchestration, large context assembly) peg the event loop for 2-4+ minutes
  • Symptom: Consecutive [WARN] socket-mode:SlackWebSocket A pong wasn't received from the server before the timeout of 5000ms! — we see runs of 4+ sequential timeouts during heavy processing
  • Impact: The gateway logs delivered reply for messages it sent to a stale/dying socket. The user never receives them. From the user's perspective, the bot goes silent.

Gateway diagnostic logs show the stuck session pattern alongside the pong timeouts:

1:38:45 PM [WARN] socket-mode:SlackWebSocket A pong wasn't received...
1:39:00 PM [WARN] socket-mode:SlackWebSocket A pong wasn't received...
1:39:09 PM [WARN] diagnostic  stuck session: state=processing age=123s queueDepth=1
1:39:18 PM [WARN] socket-mode:SlackWebSocket A pong wasn't received...
1:39:41 PM [WARN] socket-mode:SlackWebSocket A pong wasn't received...

Root cause

All processing — agent turns, tool dispatch, sub-agent orchestration, JSON parsing, context assembly, and WebSocket keepalive — runs on the same single Node.js event loop thread. When heavy turns monopolize the event loop, the Slack SDK's ping/pong handler can't fire within its 5000ms deadline.

This isn't a Slack server-side issue (as in #14248) — it's the gateway's event loop being too busy to service the pings at all.

Suggested fix

Move Slack Socket Mode WebSocket keepalive (ping/pong) to a worker_threads thread. The keepalive handler doesn't need access to session state or agent context — it just needs to respond "pong" to Slack's "ping." This is a small, isolated piece of work that would prevent connection drops regardless of how busy the main thread is.

Alternatively (or additionally):

  • Expose clientPingTimeout per Expose clientPingTimeout for Slack Socket Mode configuration #14248 — a higher timeout would reduce false positives, though it doesn't prevent genuine event loop starvation from causing drops
  • Add periodic setImmediate() yields in long-running synchronous processing paths (context assembly, transcript serialization) to give the event loop breathing room

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:session-stateSession, memory, transcript, context, or agent state can drift or corrupt.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions