Skip to content

WhatsApp health monitor stale-socket detection causes unnecessary restarts and session conflicts #54614

Description

@alimajoray-sudo

Bug Description

The channel health monitor treats WhatsApp connections as "stale-socket" after 30 minutes of inactivity (staleEventThresholdMs: 1,800,000ms), even when the Baileys WebSocket is perfectly healthy and connected. This triggers unnecessary reconnection cycles that cause status 440 (session conflict) errors, ultimately making WhatsApp unavailable.

Root Cause

In gateway-cli-*.js (channel health evaluator), Telegram is explicitly excluded from stale-socket detection:

if (policy.channelId !== "telegram" && ...) {
  // stale-socket logic
}

WhatsApp (Baileys) is not excluded, but it behaves similarly to Telegram — long idle periods between messages are normal, especially overnight. The socket is still connected and functional; there are just no inbound/outbound events to update lastEventAt.

Impact

  • 865 unnecessary restarts in a single day (every ~35 minutes overnight when no messages arrive)
  • Each restart creates a new Baileys/WhatsApp Web session. If the old session has not fully closed → status 440: session conflict
  • Session conflicts cause the connection to bounce multiple times, creating windows where "No active WhatsApp Web listener" errors occur
  • Cron jobs that send WhatsApp messages (e.g., scheduled reports) fail during these windows
  • In our case: Flip Finder WhatsApp delivery had 52% error rate, all caused by this issue

Evidence from logs

# Health monitor kills the connection every 35 min overnight:
2026-03-25T01:49:02 [health-monitor] [whatsapp:default] health-monitor: restarting (reason: stale-socket)
2026-03-25T02:24:02 [health-monitor] [whatsapp:default] health-monitor: restarting (reason: stale-socket)
2026-03-25T02:59:02 [health-monitor] [whatsapp:default] health-monitor: restarting (reason: stale-socket)
... (repeats every ~35 min)

# Restart causes session conflict:
2026-03-25T18:15:03 [whatsapp] Web connection closed (status 440: session conflict)

# Which causes send failures:
2026-03-21T12:12:13 [ws] ⇄ res ✗ send errorCode=UNAVAILABLE errorMessage=Error: No active WhatsApp Web listener

Suggested Fix

Option A (minimal): Exclude WhatsApp from stale-socket detection, same as Telegram:

if (policy.channelId !== "telegram" && policy.channelId !== "whatsapp" && ...) {

Option B (better): Expose staleEventThresholdMs as a per-channel config option so users can tune it:

{
  "channels": {
    "whatsapp": {
      "healthMonitor": {
        "enabled": true,
        "staleEventThresholdMs": 21600000  // 6 hours instead of 30 min
      }
    }
  }
}

Option C (best): Use Baileys's own connection state (connection: "open" / "close") as the health signal instead of relying on message event timestamps. A connected but idle socket is healthy.

Current Workaround

Disabling the health monitor for WhatsApp:

"healthMonitor": { "enabled": false }

This works but loses the benefit of detecting genuinely dead connections.

Environment

  • OpenClaw version: latest (as of 2026-03-25)
  • WhatsApp provider: Baileys (@whiskeysockets/baileys)
  • OS: macOS (Apple Silicon)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions