# Telegram Adapter Diagnostics ## Quick Health Check ```bash # 1. Is the adapter connected? journalctl --user -u hermes-gateway --since '10 min ago' --no-pager | grep -i "telegram" | tail -5 # 2. Is the proxy working? curl -s -o /dev/null -w "%{http_code}" --proxy http://127.0.0.1:7890 https://api.telegram.org # 3. Is the bot alive? # (replace TOKEN with actual bot token from ~/.hermes/.env) curl -s "https://api.telegram.org/bot/getMe" --proxy http://127.0.0.1:7890 # 4. Is the bot in the target group? curl -s "https://api.telegram.org/bot/getChatMember?chat_id=&user_id=" --proxy http://127.0.0.1:7890 ``` ## Diagnosing "Bot Not Processing Group Messages" ### Step 1: Check if adapter is alive ```bash journalctl --user -u hermes-gateway --no-pager --since '1 hour ago' | grep "\[Telegram\]" | tail -10 ``` - If only crash/reconnect-failed logs → adapter is dead, restart gateway - If "Reconnecting telegram" entries → watcher is alive, proxy may be down - If no Telegram logs at all → either adapter connected silently or watcher died ### Step 2: Check if proxy is the issue ```bash curl -s -o /dev/null -w "%{http_code}" --proxy http://127.0.0.1:7890 https://api.telegram.org # 302 = proxy working, timeout/ConnectError = proxy down ``` ### Step 3: Check bot group membership ```bash # Get bot info python3 -c " import json, urllib.request with open('/home/openclaw/.hermes/.env') as f: token = [l.split('=',1)[1].strip() for l in f if l.startswith('TELEGRAM_BOT_TOKEN')][0] proxy = urllib.request.ProxyHandler({'https': 'http://127.0.0.1:7890'}) opener = urllib.request.build_opener(proxy) resp = opener.open(f'https://api.telegram.org/bot{token}/getChatMember?chat_id=&user_id=') print(json.loads(resp.read())) " ``` ### Step 4: Check config In `~/.hermes/config.yaml`, under `telegram:`: - `free_response_chats` or `free_response_channels` must include the group ID - `channel_prompts` can be set per group for custom behavior - `allowed_chats` when set acts as a whitelist (empty = no restriction) - `require_mention: true` means bot only responds when @mentioned (unless in `free_response_chats`) **Editing channel_prompts**: Values are unicode-escaped with YAML line continuations (`\` at line end). Don't use `patch()` — it breaks on multi-line unicode. Use Python regex instead: ```python import re with open('/home/openclaw/.hermes/config.yaml') as f: content = f.read() # Match across line breaks with [\s\\]* for YAML continuations pattern = re.compile(r'\\uXXXX[\s\\]*\\uYYYY') content = pattern.sub(r'\\uNEW1\\uNEW2', content) with open('/home/openclaw/.hermes/config.yaml', 'w') as f: f.write(content) # Always verify YAML validity after import yaml; yaml.safe_load(open('/home/openclaw/.hermes/config.yaml')) ``` The same prompt string is duplicated across `slack`, `discord`, `mattermost`, and `telegram` sections — replace in all 4. ### Step 5: Check forwarder ```bash # Is the forwarder running? docker ps | grep forwarder # Check forwarder config sqlite3 ~/TelegramForwarder/db/forward.db "SELECT * FROM chats;" sqlite3 ~/TelegramForwarder/db/forward.db "SELECT * FROM forward_rules;" sqlite3 ~/TelegramForwarder/db/forward.db "SELECT * FROM keywords;" # Check recent forwarding activity docker logs telegram-forwarder --tail 20 | grep "已发送" ``` ## Gateway Restart Constraints - **Cannot restart from inside the gateway**: `hermes gateway restart` is blocked when run from a gateway session (SIGTERM propagation prevention) - **`kill ` also blocked**: Security scanner intercepts `kill` commands targeting the gateway PID. Terminal returns `Blocked: cannot restart or stop the gateway from inside the gateway process.` - **Workaround 1**: User runs `hermes gateway restart` from a separate SSH shell (recommended) - **Workaround 2**: `systemctl --user restart hermes-gateway` from a separate shell - **Workaround 3**: Write a small helper script to `/tmp/` and ask user to run it manually ## Reconnect Watcher Architecture When a platform adapter hits a fatal error: 1. `_set_fatal_error()` → sets `adapter._running = False` 2. `_handle_adapter_fatal_error()` → disconnects adapter, removes from `self.adapters` 3. If `fatal_error_retryable=True` → adds to `self._failed_platforms` with backoff 4. `_platform_reconnect_watcher()` → background asyncio task, retries with exponential backoff (30s→300s cap) **Known bug**: The watcher task can silently die. No upstream fix yet. Workaround: external gateway restart. **Root cause (observed 2026-06-23)**: When multiple platforms crash simultaneously (Telegram + WeChat + QQBot), the watcher may die. Evidence: `journalctl` shows the fatal error at 09:27 but ZERO "Reconnecting telegram" or "Reconnect telegram error" entries afterward — the watcher's `while self._running` loop exited without logging. On a previous crash (2026-06-22) with only Telegram affected, the watcher worked correctly and kept retrying with backoff. **Edge case — already-queued platform**: `_handle_adapter_fatal_error()` checks `adapter.platform not in self._failed_platforms` before queueing. If Telegram was already in the queue from a prior failure, the new fatal error doesn't re-queue or reset the backoff. The existing entry's `next_retry` timer may be at the 300s cap, causing long silent gaps between reconnection attempts even when the watcher IS alive. **Definitive diagnosis**: If after a crash you see zero reconnection attempt logs for >10 minutes, the watcher is dead. Restart the gateway from an external shell.