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)
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: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
"No active WhatsApp Web listener"errors occurEvidence from logs
Suggested Fix
Option A (minimal): Exclude WhatsApp from stale-socket detection, same as Telegram:
Option B (better): Expose
staleEventThresholdMsas 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:
This works but loses the benefit of detecting genuinely dead connections.
Environment