openclaw - 💡(How to fix) Fix Telegram polling stalls with `getUpdates failed` despite `channels.telegram.proxy` configured (v2026.4.24, macOS) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#72674Fetched 2026-04-28 06:33:32
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
closed ×1commented ×1

On a 国内 (China-mainland) network where api.telegram.org requires HTTP proxy, telegram polling enters a stall loop with Network request for 'getUpdates' failed! even when channels.telegram.proxy is set in ~/.openclaw/openclaw.json. The bundled HTTP proxy (Clash Verge) at http://127.0.0.1:7890 is verified to reach api.telegram.org via plain curl. Workaround: inject setGlobalDispatcher(new EnvHttpProxyAgent()) at dist/index.js boot — but this should be wired natively by the gateway when proxy env vars or channels.telegram.proxy are present.

Error Message

outcome=error ... error=Network request for 'getUpdates' failed!

Root Cause

On a 国内 (China-mainland) network where api.telegram.org requires HTTP proxy, telegram polling enters a stall loop with Network request for 'getUpdates' failed! even when channels.telegram.proxy is set in ~/.openclaw/openclaw.json. The bundled HTTP proxy (Clash Verge) at http://127.0.0.1:7890 is verified to reach api.telegram.org via plain curl. Workaround: inject setGlobalDispatcher(new EnvHttpProxyAgent()) at dist/index.js boot — but this should be wired natively by the gateway when proxy env vars or channels.telegram.proxy are present.

Fix Action

Fix / Workaround

On a 国内 (China-mainland) network where api.telegram.org requires HTTP proxy, telegram polling enters a stall loop with Network request for 'getUpdates' failed! even when channels.telegram.proxy is set in ~/.openclaw/openclaw.json. The bundled HTTP proxy (Clash Verge) at http://127.0.0.1:7890 is verified to reach api.telegram.org via plain curl. Workaround: inject setGlobalDispatcher(new EnvHttpProxyAgent()) at dist/index.js boot — but this should be wired natively by the gateway when proxy env vars or channels.telegram.proxy are present.

The static path looks correct. Either (a) account.config.proxy resolves to undefined at runtime in some merge edge case, or (b) proxyFetch is constructed but the resulting dispatcher isn't applied to the actual grammy transport, or (c) some retry/fallback path bypasses it. I didn't trace down to grammy Bot construction details.

Workaround that works (hotpatch)

Code Example

{
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "<your bot token>",
      "proxy": "http://127.0.0.1:7890",
      "dmPolicy": "allowlist",
      "allowFrom": ["tg:<your chat id>"]
    }
  }
}

---

[telegram] Polling stall detected (active getUpdates stuck for 543.01s); forcing restart.
[telegram] [diag] polling cycle finished reason=polling stall detected ...
  outcome=error ... error=Network request for 'getUpdates' failed!
[telegram] polling runner stopped (polling stall detected); restarting in 2.41s.
[telegram] [diag] closing stale transport before rebuild
[telegram] [diag] rebuilding transport for next polling cycle

---

TOKEN=$(jq -r .channels.telegram.botToken ~/.openclaw/openclaw.json)
curl -s -m 10 -x http://127.0.0.1:7890 "https://api.telegram.org/bot${TOKEN}/getMe" | jq .ok
# → true
curl -s -m 10 -x http://127.0.0.1:7890 "https://api.telegram.org/bot${TOKEN}/getUpdates?timeout=5"
# → {"ok":true,"result":[]}

---

const proxyFetch = opts.proxyFetch ?? (account.config.proxy ? makeProxyFetch(account.config.proxy) : void 0);

---

import process from "node:process";
 import { fileURLToPath } from "node:url";
+try {
+  const { setGlobalDispatcher, EnvHttpProxyAgent } = await import("undici");
+  if (process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy) {
+    setGlobalDispatcher(new EnvHttpProxyAgent());
+  }
+} catch (_e) { /* undici unavailable */ }
 //#region src/index.ts
RAW_BUFFERClick to expand / collapse

Telegram polling stalls indefinitely with Network request for 'getUpdates' failed! despite channels.telegram.proxy configured (v2026.4.24, macOS)

Summary

On a 国内 (China-mainland) network where api.telegram.org requires HTTP proxy, telegram polling enters a stall loop with Network request for 'getUpdates' failed! even when channels.telegram.proxy is set in ~/.openclaw/openclaw.json. The bundled HTTP proxy (Clash Verge) at http://127.0.0.1:7890 is verified to reach api.telegram.org via plain curl. Workaround: inject setGlobalDispatcher(new EnvHttpProxyAgent()) at dist/index.js boot — but this should be wired natively by the gateway when proxy env vars or channels.telegram.proxy are present.

Environment

  • macOS 25.4.0 (Apple Silicon M3, 16GB)
  • node v24.14.1 (fnm)
  • openclaw v2026.4.24 (npm latest), launchd-managed
  • Clash Verge HTTP proxy http://127.0.0.1:7890 (TCP only, no TUN)
  • All standard proxy env vars set in ~/Library/LaunchAgents/ai.openclaw.gateway.plist EnvironmentVariables:
    • HTTP_PROXY / HTTPS_PROXY / http_proxy / https_proxy / all_proxy / ALL_PROXY / NO_PROXY / no_proxy
  • macOS system proxy ON (HTTPEnable=1, HTTPSEnable=1, port 7890)

Repro

~/.openclaw/openclaw.json:

{
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "<your bot token>",
      "proxy": "http://127.0.0.1:7890",
      "dmPolicy": "allowlist",
      "allowFrom": ["tg:<your chat id>"]
    }
  }
}

Then: launchctl kickstart -k gui/$UID/ai.openclaw.gateway

Expected

Telegram polling reaches api.telegram.org through 127.0.0.1:7890, getUpdates succeeds.

Actual

~/.openclaw/logs/gateway.err.log:

[telegram] Polling stall detected (active getUpdates stuck for 543.01s); forcing restart.
[telegram] [diag] polling cycle finished reason=polling stall detected ...
  outcome=error ... error=Network request for 'getUpdates' failed!
[telegram] polling runner stopped (polling stall detected); restarting in 2.41s.
[telegram] [diag] closing stale transport before rebuild
[telegram] [diag] rebuilding transport for next polling cycle

Repeats indefinitely. Each polling cycle consumes 136s–543s before stall detection. CPU spikes during retry.

Verification proxy itself works

TOKEN=$(jq -r .channels.telegram.botToken ~/.openclaw/openclaw.json)
curl -s -m 10 -x http://127.0.0.1:7890 "https://api.telegram.org/bot${TOKEN}/getMe" | jq .ok
# → true
curl -s -m 10 -x http://127.0.0.1:7890 "https://api.telegram.org/bot${TOKEN}/getUpdates?timeout=5"
# → {"ok":true,"result":[]}

Proxy reaches telegram api in ~1s. The issue is openclaw not threading the proxy into the telegram polling fetcher.

Code paths inspected (dist v2026.4.24)

  • dist/extensions/telegram/probe-ChPXZhx2.js:302 — appears to construct proxyFetch from account.config.proxy:
    const proxyFetch = opts.proxyFetch ?? (account.config.proxy ? makeProxyFetch(account.config.proxy) : void 0);
  • dist/extensions/telegram/account-config-Cifs-fXF.js:8mergeTelegramAccountConfig should expose proxy via ...base spread of cfg.channels.telegram.
  • dist/extensions/telegram/monitor-polling.runtime-cvefT1B7.js:280-286 — passes proxyFetch: this.opts.proxyFetch into createTelegramBot.
  • dist/extensions/telegram/bot-gUR32RLX.js:5086resolveTelegramTransport(opts.proxyFetch, { network: telegramCfg.network }).

The static path looks correct. Either (a) account.config.proxy resolves to undefined at runtime in some merge edge case, or (b) proxyFetch is constructed but the resulting dispatcher isn't applied to the actual grammy transport, or (c) some retry/fallback path bypasses it. I didn't trace down to grammy Bot construction details.

Workaround that works (hotpatch)

Patching dist/index.js to install a global undici dispatcher at boot resolves the stall:

 import process from "node:process";
 import { fileURLToPath } from "node:url";
+try {
+  const { setGlobalDispatcher, EnvHttpProxyAgent } = await import("undici");
+  if (process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy) {
+    setGlobalDispatcher(new EnvHttpProxyAgent());
+  }
+} catch (_e) { /* undici unavailable */ }
 //#region src/index.ts

After this patch + launchctl kickstart -k:

  • Polling stall errors gone
  • getUpdates reaches api.telegram.org and returns business responses (incl. 409 Conflict: terminated by other getUpdates request if multiple bot instances exist — separate issue)
  • Telegram messages flow normally

This is a dist/ patch and gets overwritten on npm i -g openclaw@latest. Suggested upstream fixes:

Option A — global dispatcher fallback at gateway boot

Install EnvHttpProxyAgent as setGlobalDispatcher at the entry when standard proxy env vars are present, similar to the patch above. This handles the broad case of "user set HTTP_PROXY but a transitive lib doesn't honor it".

Option B — explicit dispatcher injection into grammy bot

Confirm at runtime that account.config.proxy from cfg.channels.telegram.proxy actually reaches the grammy Bot instance's HTTP client, and add a runtime log line at startup like [telegram] account=<id> proxy=<url|none> for visibility (currently proxy: … only appears in the static config dump, not in the polling start log).

Option C — document explicitly

If channels.telegram.proxy is intentionally probe-only (not polling), document that explicitly and require either TUN-mode proxy or setGlobalDispatcher as the supported approach for restricted networks.

Other observations during repro

  • [plugins] memory-core: managed dreaming cron could not be reconciled (cron service unavailable) — appears after telegram-induced lane stalls; suggests a single failed lane (session:agent:main:main:heartbeat) cascades to lock cron service. Even after the underlying network recovers, gateway never self-heals; only launchctl kickstart -k clears the state. Worth a separate auto-recovery issue.
  • [plugins] bonjour: watchdog detected non-announced service; attempting re-advertise — recurring every ~21 minutes regardless of telegram health.

Happy to test a fix on this machine.

extent analysis

TL;DR

  • The most likely fix is to install a global EnvHttpProxyAgent dispatcher at gateway boot when standard proxy environment variables are present.

Guidance

  • Verify that the channels.telegram.proxy configuration is correctly set in ~/.openclaw/openclaw.json.
  • Check that the proxy environment variables (HTTP_PROXY, HTTPS_PROXY, etc.) are set in ~/Library/LaunchAgents/ai.openclaw.gateway.plist.
  • Consider implementing Option A, installing EnvHttpProxyAgent as setGlobalDispatcher at gateway boot, to handle cases where transitive libraries don't honor the proxy settings.
  • If the issue persists, try injecting the EnvHttpProxyAgent dispatcher explicitly into the grammy bot instance (Option B) to ensure the proxy is used for polling.

Example

import process from "node:process";
import { fileURLToPath } from "node:url";
try {
  const { setGlobalDispatcher, EnvHttpProxyAgent } = await import("undici");
  if (process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy) {
    setGlobalDispatcher(new EnvHttpProxyAgent());
  }
} catch (_e) { /* undici unavailable */ }

Notes

  • The provided workaround patching dist/index.js resolves the issue but gets overwritten on npm i -g openclaw@latest.
  • The root cause appears to be the openclaw gateway not threading the proxy into the telegram polling fetcher.

Recommendation

  • Apply the workaround by installing a global EnvHttpProxyAgent dispatcher at gateway boot, as it handles the broad case of users setting HTTP_PROXY but transitive libraries not honoring it.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Telegram polling stalls with `getUpdates failed` despite `channels.telegram.proxy` configured (v2026.4.24, macOS) [1 comments, 2 participants]