
## Case 7: Token in `.env` But Revoked — Bot Deleted on Telegram Side (2026-06-22)

### Symptom

User reports "telegram stuck on sending message" — messages appear to send in the Telegram UI but never produce a response from the bot. Happens intermittently but currently persistent.

### Initial presentation

Gateway process is `active` (running since the recent Hermes update restart). No Telegram-specific errors visible in a quick check.

### Investigation

**1. Gateway is running — but no Telegram log entries**

```bash
systemctl --user is-active hermes-gateway
# → active, PID 2838174, since 15:35

journalctl --user -u hermes-gateway --since "15:30" --no-pager | grep -i telegram
# → (empty — nothing from this PID)
```

**2. API connectivity to Telegram is fine**

```bash
curl -s --connect-timeout 5 --max-time 10 -o /dev/null -w "%{http_code} %{time_total}s %{remote_ip}" https://api.telegram.org/
# → 302 0.864343s 149.154.166.110
```

Network is working. Resolves to the known Telegram IP. No packet loss, no DNS failure.

**3. Bot token returns 404**

```bash
curl -s --max-time 10 "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getMe"
# → {"ok":false,"error_code":404,"description":"Not Found"}
```

Same response as an explicitly invalid token:
```bash
curl -s --max-time 10 "https://api.telegram.org/botINVALID_TOKEN/getMe"
# → {"ok":false,"error_code":404,"description":"Not Found"}
```

This is NOT a 401 (revoked) — it's a 404 (bot doesn't exist on Telegram's servers).

**4. Token format is valid**

```bash
python3 -c "
e = open('/home/rurouni/.hermes/.env').read()
import re
m = re.search(r'TELEGRAM_BOT_TOKEN=(.+)', e)
if m:
    t = m.group(1)
    print(f'Token length: {len(t)}')
    print(f'Has colon: {\":\" in t}')
    print(f'Format regex: {bool(re.match(r\"\d+:[A-Za-z0-9_-]{30,}$\", t))}')
"
# → Token length: 46
# → Has colon: True
# → Format regex: True
```

Token is 46 chars, contains colon, passes the `\d+:[A-Za-z0-9_-]{30,}` regex. Format is NOT the problem.

**5. Timeline reconstruction**

```bash
stat ~/.hermes/.env | grep Modify
# → Modify: 2026-06-21 12:12:54

journalctl --user -u hermes-gateway --no-pager | grep -E 'Telegram' | tail -3
# → Jun 21 09:23:07 — Last Telegram message received
```

The `.env` was modified at **12:12 on Jun 21** — approximately 3 hours after the last successful Telegram message at 09:23. Timeline:

| Time | Event |
|---|---|
| Jun 21 07:16 | Network errors to api.telegram.org (both primary + fallback failed) |
| Jun 21 09:23 | Last successful Telegram message processed |
| **Jun 21 12:12** | **`.env` modified** — likely the token was changed here |
| Jun 22 15:32 | Hermes update, gateway restarted |
| Jun 22 ~15:35 | Gateway restart → Telegram tries to init with invalid token → silent failure |

The modification at 12:12 could be:
- A manual attempt to fix the earlier network failure by generating a new token
- An unrelated config edit that accidentally changed the token
- The bot was deleted around this time and `.env` was updated with a bad token

**6. Pre-update snapshot comparison**

```bash
diff <(grep TELEGRAM_BOT_TOKEN ~/.hermes/state-snapshots/20260622-223214-pre-update/.env) \
     <(grep TELEGRAM_BOT_TOKEN ~/.hermes/.env)
# → No difference — same token in both
```

The token was already invalid BEFORE the Hermes update. The update didn't cause this — it just made it visible by restarting the gateway (which re-authenticated and failed).

### Root Cause

**The Telegram bot was deleted or the token was revoked on Telegram's side.** The token exists in `.env`, has valid format and length, passes the format regex, and was the same before the Hermes update — but Telegram's API returns 404, meaning the bot ID `8796348132` is not registered.

This is distinct from all previous cases:
- **Not Case 1/2/3** (network failure, polling wedge, gateway crash) — gateway process is running fine, network works
- **Not Case 4** (409 polling conflict) — no competing polling sessions
- **Not Case 5** (flood control) — no flood control entries anywhere in logs
- **Not Case 6** (`***` corruption) — token is the real 46-char value, not literal asterisks

This is a **Telegram-side account/bot issue** — the bot was likely deleted via BotFather, or Telegram removed it for inactivity/infraction.

### Fix

```bash
# Cannot be automated. User must:
# 1. Message @BotFather on Telegram
# 2. Use /newbot to create a new bot
# 3. Paste the new token when prompted
hermes setup telegram
```

### Diagnostic Lesson

- **404 on `getMe`** does not always mean "malformed token." A properly formatted 46-char token can still 404 if the bot was deleted on Telegram's side.
- **Format validation is a negative test only** — passing regex does NOT mean the token is active. Only `getMe` with `ok:true` confirms an active bot.
- **`getMe` response codes matter** — distinguish 401 (revoked, still existed once) from 404 (never existed or was fully deleted). 404 is harder to debug because it looks like a typo.
- **Timeline reconstruction is essential.** Comparing `.env` modification time with last successful gateway Telegram activity reveals whether the config changed before or after the failure.
- **Pre-update backups don't always help.** If the token was already invalid before the backup was taken, the backup preserves the same bad value. Don't assume a "before update" snapshot means "working."
- **The `.env` file itself is the source of truth** (gateway reads `TELEGRAM_BOT_TOKEN` from env, not from `config.yaml`'s `gateway.telegram.token`). But `.env` can hold a bad token just as easily as `config.yaml` can.
- **A Hermes update that restarts the gateway can make a pre-existing token problem visible.** The old gateway process may have held a working long-poll session despite the token being bad — the new session must authenticate fresh.
- **No Telegram log entries + gateway active = auth failure.** This pattern is pathognomonic: the Telegram adapter initializes, calls `getMe`, gets a non-`ok` response, and enters the reconnect loop without ever logging a meaningful error. If you see this, skip network testing and go straight to `getMe` verification.
