Skip to content

Telegram subsystem: getUpdates polling silently non-functional despite reachable API #71066

Description

@uttungmalkan-source

Telegram subsystem: getUpdates polling silently non-functional despite reachable API

Summary

The Telegram channel's long-polling never consumes updates from Telegram's Bot API, even though:

  • The bot token is valid (Telegram confirms getMe returns the bot profile)
  • api.telegram.org is fully reachable from the host via plain curl (HTTP 200 in ~500ms)
  • The exact same undici fetch configuration, run as a standalone script from the same Node installation, succeeds instantly

The subsystem logs fetch fallback: enabling sticky IPv4-only dispatcher (codes=ETIMEDOUT,EHOSTUNREACH) every ~7 seconds but never recovers. Messages sent to the bot from clients remain pending on Telegram's servers indefinitely.

Environment

  • OpenClaw: 2026.4.22 (commit 00bd2cf)
  • OS: macOS 26.2 (Darwin 25.2.0), arm64
  • Node: tested on v25.9.0 AND v22.22.2 — identical behavior
  • Channel binding: loopback (ws://127.0.0.1:18789)
  • Network: home broadband in India, no corporate VPN or proxy (env | grep proxy is empty, and the LaunchAgent inherits no HTTP_PROXY/HTTPS_PROXY)

Reproduction

  1. openclaw channels add --channel telegram --token <valid-bot-token>
  2. Send a message to the bot from any Telegram client
  3. Watch /tmp/openclaw/openclaw-*.log

Expected

  • Bot receives updates via long-poll (getUpdates)
  • Gateway creates a session and routes to the agent

Actual

  • Repeated WARN log every ~7s: {"subsystem":"telegram/network"} fetch fallback: enabling sticky IPv4-only dispatcher (codes=ETIMEDOUT,EHOSTUNREACH)
  • curl https://api.telegram.org/bot<token>/getUpdates from the same host shows pending updates accumulating — the gateway never consumes them

Evidence that the network is fine

# Plain curl from the same shell that launches the gateway:
$ curl -sS --max-time 8 -o /dev/null -w "HTTP %{http_code} · %{time_total}s · ip %{remote_ip}\n" https://api.telegram.org
HTTP 302 · 0.49s · ip 149.154.166.110

# getMe works instantly:
$ curl -sS "https://api.telegram.org/bot<token>/getMe"
{"ok":true,"result":{"id":...,"is_bot":true,"first_name":"Nora","username":"..."}}

Evidence that undici (the transport the subsystem uses) is fine

Running a standalone script against the same undici package installed under /opt/homebrew/lib/node_modules/openclaw/node_modules/undici/ with Node v22.22.2:

import { fetch, Agent } from '<openclaw-path>/node_modules/undici/index.js';

async function test(name, opts) {
  const d = new Agent(opts);
  const r = await fetch('https://api.telegram.org/bot<token>/getMe', { dispatcher: d });
  console.log(`${name}: ${r.status}`);
}
await test('default', {});
await test('ipv4-family=4', { connect: { family: 4 } });
await test('autoSelect+300ms', { connect: { autoSelectFamily: true, autoSelectFamilyAttemptTimeout: 300 } });

Output:

default: HTTP 200 · 531ms · ok=true
ipv4-family=4: HTTP 200 · 509ms · ok=true
autoSelect-true: HTTP 200 · 566ms · ok=true

So Node, undici, and every dispatcher variant the telegram/network subsystem attempts are all functional from the exact same environment. The failure is specific to the long-running gateway process.

Things I've ruled out

  • Bot token validity — confirmed via getMe
  • DNS / network reachability — curl succeeds consistently
  • Node version — same behavior on v25 and v22
  • Happy-eyeballs tuning — setting OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1 and OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first in the LaunchAgent env stops the error log spam but does not start polling working; updates continue to pile up
  • Gateway restart — launchctl bootout/bootstrap, openclaw gateway restart, full openclaw doctor --fix — none recover polling
  • HTTP_PROXY/HTTPS_PROXY env — not set in gateway plist nor in shell
  • Homebrew library rot (libsimdutf.33.dylib was missing; brew upgrade merve fixed the CLI path, no effect on the Telegram subsystem)

Hypotheses (not yet ruled out)

  1. The telegram/network subsystem's dispatcher gets into a bad state on first failure and never fully recovers — possibly a connection-pool-holding-stale-sockets issue specific to the subsystem's keep-alive settings (keepAliveTimeout: 30s, keepAliveMaxTimeout: 600s) combined with long-poll semantics.
  2. The "sticky IPv4-only dispatcher" fallback is re-entered every request instead of being reused, causing connection churn that appears as ETIMEDOUT.
  3. Something specific to how the LaunchAgent spawns the Node process (PATH, TMPDIR, or cgroup/macOS-sandbox differences) vs. the same Node binary invoked from a user shell.

Suggested debug next steps

  • Add log.debug logging when the IPv4-only dispatcher is actually constructed vs. reused — the current WARN log fires on every entry to the fallback path, which hides whether the dispatcher is being rebuilt or reused.
  • Log the actual undici error's cause.code and socket state, not just the normalized error codes.
  • Consider an explicit diagnostic RPC: openclaw channels debug telegram that runs a single getMe call from within the gateway process and reports full error chain.

Impact

On first install of the gateway, with a valid bot token and an otherwise-healthy network, Telegram messaging is completely non-functional — no user-facing error other than "messages don't show up."

Workaround

Polling via direct curl to api.telegram.org/bot<token>/getUpdates works; the issue is localized to the in-process dispatcher.

Metadata

Metadata

Assignees

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.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions