Problem
The Slack channel provider has a health-monitor that detects stale sockets and restarts the provider automatically (observed every ~35 minutes with reason: stale-socket). Telegram's long-polling has no equivalent watchdog.
When a NAT, proxy, or firewall silently drops the idle TCP connection used by getUpdates, the HTTP client hangs indefinitely — no error, no timeout, no disconnect event. The Telegram provider silently dies and never recovers. In my case, Telegram was dead for 12 hours with zero log output indicating a problem.
Expected Behavior
Telegram should have stall detection parity with Slack's health-monitor:
- Track the timestamp of the last successful
getUpdates response
- Periodic watchdog (e.g. every 30s) checks if elapsed time exceeds a stall threshold (e.g. 90s)
- If stalled, force-abort the current HTTP request and restart just the Telegram provider (not the whole gateway)
This is the pattern used by grammY's @grammyjs/runner (POLL_STALL_THRESHOLD_MS = 90000, POLL_WATCHDOG_INTERVAL_MS = 30000).
Additional Context
- A
getMe call could serve as a lightweight liveness probe alongside stall detection
- The HTTP client's read timeout should be set above the Telegram
timeout param (e.g. 50-60s vs 30s) but below the stall threshold, so dead connections raise timeout errors rather than hanging forever
- This is a well-known problem across Telegram bot frameworks: telegraf#735, python-telegram-bot#4069, node-telegram-bot-api#455
Logs
# Last Telegram activity before silent death:
00:16:08 [telegram] sendMessage ok chat=... message=2155
# 12 hours of only Slack health-monitor restarts, zero Telegram activity:
00:20:15 [health-monitor] [slack:default] health-monitor: restarting (reason: stale-socket)
00:55:15 [health-monitor] [slack:default] health-monitor: restarting (reason: stale-socket)
01:30:15 [health-monitor] [slack:default] health-monitor: restarting (reason: stale-socket)
...
12:35:15 [health-monitor] [slack:default] health-monitor: restarting (reason: stale-socket)
# No Telegram errors, no reconnect attempts, nothing.
Environment
- OpenClaw v2026.3.7
- Running in Docker (node:22-slim)
- Telegram provider in long-polling mode (
streaming: "off")
- Behind Docker bridge network (NAT)
Problem
The Slack channel provider has a
health-monitorthat detects stale sockets and restarts the provider automatically (observed every ~35 minutes withreason: stale-socket). Telegram's long-polling has no equivalent watchdog.When a NAT, proxy, or firewall silently drops the idle TCP connection used by
getUpdates, the HTTP client hangs indefinitely — no error, no timeout, no disconnect event. The Telegram provider silently dies and never recovers. In my case, Telegram was dead for 12 hours with zero log output indicating a problem.Expected Behavior
Telegram should have stall detection parity with Slack's health-monitor:
getUpdatesresponseThis is the pattern used by grammY's
@grammyjs/runner(POLL_STALL_THRESHOLD_MS = 90000,POLL_WATCHDOG_INTERVAL_MS = 30000).Additional Context
getMecall could serve as a lightweight liveness probe alongside stall detectiontimeoutparam (e.g. 50-60s vs 30s) but below the stall threshold, so dead connections raise timeout errors rather than hanging foreverLogs
Environment
streaming: "off")