Skip to content

Telegram inbound dispatch hangs after Inbound message log #84710

@jzcyqf

Description

@jzcyqf

OpenClaw v2026.5.18 — telegram inbound dispatch hangs after "Inbound message" log

Summary

dispatchTelegramMessage in the telegram channel sometimes never resolves: the gateway logs [telegram] Inbound message ... -> @<bot> (direct, N chars) and then nothing further fires for that turn. No model call, no failover, no error, no outbound. The same agent answered via CLI (openclaw agent --agent main --channel telegram --to <chatId> --deliver) returns in 3–4 s, proving the model/agent/auth/outbound paths all work — only the inbound channel wrapper hangs.

Environment

  • OpenClaw v2026.5.18 (50a2481) on macOS 25.4 (Apple Silicon)
  • node v22 (libnode.141.dylib), bundle name: dist/bot-BRuINTsq.js
  • Gateway run as LaunchAgent ai.openclaw.gateway
  • Telegram channel, long-polling (no webhook)
  • Reproduced with both openai/gpt-5.5 and openrouter/google/gemini-2.5-flash as primary
  • Reproduced with channels.telegram.isolatedIngress.enabled defaulted true AND patched to false (i.e. independent of which ingress path delivers the update)
  • Also reproduced on v2026.5.12

Signature

[telegram] Inbound message telegram:<chatId> -> @<bot> (direct, N chars)
<silence — no further log lines for this turn>
  • openclaw health reports event loop ok (util ~0.01, p99 ~20 ms)
  • getWebhookInfo returns pending_update_count: 0 (the update was consumed; bot side is clean)
  • sample <gateway-pid> shows the main thread idle in kevent — no telegram/dispatch JS frames on the stack
  • The inbound is correctly persisted into agents/<agent>/sessions/sessions.json.telegram-messages.json (JSONL, last entry visible) — so the dispatcher reaches at least that write before hanging
  • No outbound TCP to api.openai.com / api.anthropic.com / openrouter.ai is opened for the hung turn

Repro recipe (intermittent but reliable within a session)

  1. Restart the gateway: launchctl kickstart -k gui/$(id -u)/ai.openclaw.gateway
  2. Send the agent a Telegram message — first message often succeeds (sometimes after a brief FailoverError if a misconfigured codex provider is in the chain)
  3. Send a second message — silently hangs
  4. All subsequent inbound for that chat also silently hang
  5. Restart again → step 2 succeeds again, etc.

CLI delivery to the same agent + chat continues to work the whole time:

openclaw agent --agent main --channel telegram --to <chatId> --deliver --json --message "ping"

returns in ~4 s with a successful sendMessage.

Workarounds tried that did NOT help

  • Model swap (gpt-5.5 → gemini-2.5-flash, both as agent primary and agents.defaults.model.primary)
  • openclaw doctor --fix --yes (migrated codex OAuth sidecar → inline, tightened perms, refreshed plugin registry — gateway restart yes, dispatcher hang no)
  • Archiving 506 orphan transcript files (~176 MB) flagged by doctor
  • OPENCLAW_DEBUG_TELEGRAM_INGRESS=1 — the debug log inside processMessage is conditional on options.receivedAtMs being set upstream, which it isn't in normal polling, so it doesn't surface the hang location
  • Patching dist/probe-2l5SF_IE2.js:532 to default opts.isolatedIngress?.enabled ?? false (force legacy #runPollingCycle path) — message still hangs after "Inbound message" log

Suspected location

dispatchTelegramMessage in bot-BRuINTsq.js (around line 5875 in v2026.5.18). The await at the call site (~line 6979) never resolves and never throws. The reply-fence lane lock, status reactions, or draft-stream finalize are my prime suspects for the leaked promise, but I couldn't pin down which without a debug build.

Useful next steps for the maintainer

  • Wrap dispatchTelegramMessage in a watchdog log: emit a structured event at function entry, at fence-acquire, at each await boundary, at function exit. Right now the only signal is "Inbound message logged, then nothing."
  • Add a per-chat lane-lock timeout with a force-release + structured error log. Persistent silent hangs are worse than a visible timeout error.
  • Confirm whether the dispatcher reads/writes any state file (e.g. sessions.json.telegram-messages.json, sessions.json.telegram-sent-messages.json) under a lock that could be held by a prior turn.

Happy to provide a full sample output, gateway.log slice, or verbose-log slice on request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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