From ddeb4239443f9a548c7c2ac15cbcaec0d8889336 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 13 Mar 2026 01:45:47 +0000 Subject: [PATCH] fix: quiet Telegram command overflow retry logs --- CHANGELOG.md | 1 + docs/channels/telegram.md | 8 ++++--- docs/channels/troubleshooting.md | 13 +++++----- docs/help/faq.md | 10 +++++--- src/telegram/bot-native-command-menu.test.ts | 25 ++++++++++---------- src/telegram/bot-native-command-menu.ts | 22 +++++++++++++++++ 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 571d67255fd..b5c2577f63b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ Docs: https://docs.openclaw.ai - Agents/failover: classify z.ai `network_error` stop reasons as retryable timeouts so provider connectivity failures trigger fallback instead of surfacing raw unhandled-stop-reason errors. (#43884) Thanks @hougangdev. - Memory/session sync: add mode-aware post-compaction session reindexing with `agents.defaults.compaction.postIndexSync` plus `agents.defaults.memorySearch.sync.sessions.postCompactionForce`, so compacted session memory can refresh immediately without forcing every deployment into synchronous reindexing. (#25561) thanks @rodrigouroz. - Telegram/model picker: make inline model button selections persist the chosen session model correctly, clear overrides when selecting the configured default, and include effective fallback models in `/models` button validation. (#40105) Thanks @avirweb. +- Telegram/native command sync: suppress expected `BOT_COMMANDS_TOO_MUCH` retry error noise, add a final fallback summary log, and document the difference between command-menu overflow and real Telegram network failures. - Mattermost/reply media delivery: pass agent-scoped `mediaLocalRoots` through shared reply delivery so allowed local files upload correctly from button, slash-command, and model-picker replies. (#44021) Thanks @LyleLiu666. - Plugins/env-scoped roots: fix plugin discovery/load caches and provenance tracking so same-process `HOME`/`OPENCLAW_HOME` changes no longer reuse stale plugin state or misreport `~/...` plugins as untracked. (#44046) thanks @gumadeiras. - Gateway/session discovery: discover disk-only and retired ACP session stores under custom templated `session.store` roots so ACP reconciliation, session-id/session-label targeting, and run-id fallback keep working after restart. (#44176) thanks @gumadeiras. diff --git a/docs/channels/telegram.md b/docs/channels/telegram.md index f2467d12b0a..a0c679988d3 100644 --- a/docs/channels/telegram.md +++ b/docs/channels/telegram.md @@ -335,9 +335,10 @@ curl "https://api.telegram.org/bot/getUpdates" If native commands are disabled, built-ins are removed. Custom/plugin commands may still register if configured. - Common setup failure: + Common setup failures: - - `setMyCommands failed` usually means outbound DNS/HTTPS to `api.telegram.org` is blocked. + - `setMyCommands failed` with `BOT_COMMANDS_TOO_MUCH` means the Telegram menu still overflowed after trimming; reduce plugin/skill/custom commands or disable `channels.telegram.commands.native`. + - `setMyCommands failed` with network/fetch errors usually means outbound DNS/HTTPS to `api.telegram.org` is blocked. ### Device pairing commands (`device-pair` plugin) @@ -843,7 +844,8 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ - authorize your sender identity (pairing and/or numeric `allowFrom`) - command authorization still applies even when group policy is `open` - - `setMyCommands failed` usually indicates DNS/HTTPS reachability issues to `api.telegram.org` + - `setMyCommands failed` with `BOT_COMMANDS_TOO_MUCH` means the native menu has too many entries; reduce plugin/skill/custom commands or disable native menus + - `setMyCommands failed` with network/fetch errors usually indicates DNS/HTTPS reachability issues to `api.telegram.org` diff --git a/docs/channels/troubleshooting.md b/docs/channels/troubleshooting.md index 2848947c479..a7850801948 100644 --- a/docs/channels/troubleshooting.md +++ b/docs/channels/troubleshooting.md @@ -44,12 +44,13 @@ Full troubleshooting: [/channels/whatsapp#troubleshooting-quick](/channels/whats ### Telegram failure signatures -| Symptom | Fastest check | Fix | -| --------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------- | -| `/start` but no usable reply flow | `openclaw pairing list telegram` | Approve pairing or change DM policy. | -| Bot online but group stays silent | Verify mention requirement and bot privacy mode | Disable privacy mode for group visibility or mention bot. | -| Send failures with network errors | Inspect logs for Telegram API call failures | Fix DNS/IPv6/proxy routing to `api.telegram.org`. | -| Upgraded and allowlist blocks you | `openclaw security audit` and config allowlists | Run `openclaw doctor --fix` or replace `@username` with numeric sender IDs. | +| Symptom | Fastest check | Fix | +| ----------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------- | +| `/start` but no usable reply flow | `openclaw pairing list telegram` | Approve pairing or change DM policy. | +| Bot online but group stays silent | Verify mention requirement and bot privacy mode | Disable privacy mode for group visibility or mention bot. | +| Send failures with network errors | Inspect logs for Telegram API call failures | Fix DNS/IPv6/proxy routing to `api.telegram.org`. | +| `setMyCommands` rejected at startup | Inspect logs for `BOT_COMMANDS_TOO_MUCH` | Reduce plugin/skill/custom Telegram commands or disable native menus. | +| Upgraded and allowlist blocks you | `openclaw security audit` and config allowlists | Run `openclaw doctor --fix` or replace `@username` with numeric sender IDs. | Full troubleshooting: [/channels/telegram#troubleshooting](/channels/telegram#troubleshooting) diff --git a/docs/help/faq.md b/docs/help/faq.md index 453688c1c5f..37f5f96c815 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -179,7 +179,7 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS, - [I closed my terminal on Windows - how do I restart OpenClaw?](#i-closed-my-terminal-on-windows-how-do-i-restart-openclaw) - [The Gateway is up but replies never arrive. What should I check?](#the-gateway-is-up-but-replies-never-arrive-what-should-i-check) - ["Disconnected from gateway: no reason" - what now?](#disconnected-from-gateway-no-reason-what-now) - - [Telegram setMyCommands fails with network errors. What should I check?](#telegram-setmycommands-fails-with-network-errors-what-should-i-check) + - [Telegram setMyCommands fails. What should I check?](#telegram-setmycommands-fails-what-should-i-check) - [TUI shows no output. What should I check?](#tui-shows-no-output-what-should-i-check) - [How do I completely stop then start the Gateway?](#how-do-i-completely-stop-then-start-the-gateway) - [ELI5: `openclaw gateway restart` vs `openclaw gateway`](#eli5-openclaw-gateway-restart-vs-openclaw-gateway) @@ -2710,7 +2710,7 @@ openclaw logs --follow Docs: [Dashboard](/web/dashboard), [Remote access](/gateway/remote), [Troubleshooting](/gateway/troubleshooting). -### Telegram setMyCommands fails with network errors What should I check +### Telegram setMyCommands fails What should I check Start with logs and channel status: @@ -2719,7 +2719,11 @@ openclaw channels status openclaw channels logs --channel telegram ``` -If you are on a VPS or behind a proxy, confirm outbound HTTPS is allowed and DNS works. +Then match the error: + +- `BOT_COMMANDS_TOO_MUCH`: the Telegram menu has too many entries. OpenClaw already trims to the Telegram limit and retries with fewer commands, but some menu entries still need to be dropped. Reduce plugin/skill/custom commands, or disable `channels.telegram.commands.native` if you do not need the menu. +- `TypeError: fetch failed`, `Network request for 'setMyCommands' failed!`, or similar network errors: if you are on a VPS or behind a proxy, confirm outbound HTTPS is allowed and DNS works for `api.telegram.org`. + If the Gateway is remote, make sure you are looking at logs on the Gateway host. Docs: [Telegram](/channels/telegram), [Channel troubleshooting](/channels/troubleshooting). diff --git a/src/telegram/bot-native-command-menu.test.ts b/src/telegram/bot-native-command-menu.test.ts index 6f0ced96dd5..b5198b6ebc3 100644 --- a/src/telegram/bot-native-command-menu.test.ts +++ b/src/telegram/bot-native-command-menu.test.ts @@ -13,6 +13,7 @@ type SyncMenuOptions = { accountId: string; botIdentity: string; runtimeLog?: ReturnType; + runtimeError?: ReturnType; }; function syncMenuCommandsWithMocks(options: SyncMenuOptions): void { @@ -22,7 +23,7 @@ function syncMenuCommandsWithMocks(options: SyncMenuOptions): void { } as unknown as Parameters[0]["bot"], runtime: { log: options.runtimeLog ?? vi.fn(), - error: vi.fn(), + error: options.runtimeError ?? vi.fn(), exit: vi.fn(), } as Parameters[0]["runtime"], commandsToRegister: options.commandsToRegister, @@ -248,19 +249,13 @@ describe("bot-native-command-menu", () => { .mockRejectedValueOnce(new Error("400: Bad Request: BOT_COMMANDS_TOO_MUCH")) .mockResolvedValue(undefined); const runtimeLog = vi.fn(); + const runtimeError = vi.fn(); - syncTelegramMenuCommands({ - bot: { - api: { - deleteMyCommands, - setMyCommands, - }, - } as unknown as Parameters[0]["bot"], - runtime: { - log: runtimeLog, - error: vi.fn(), - exit: vi.fn(), - } as Parameters[0]["runtime"], + syncMenuCommandsWithMocks({ + deleteMyCommands, + setMyCommands, + runtimeLog, + runtimeError, commandsToRegister: Array.from({ length: 100 }, (_, i) => ({ command: `cmd_${i}`, description: `Command ${i}`, @@ -279,5 +274,9 @@ describe("bot-native-command-menu", () => { expect(runtimeLog).toHaveBeenCalledWith( "Telegram rejected 100 commands (BOT_COMMANDS_TOO_MUCH); retrying with 80.", ); + expect(runtimeLog).toHaveBeenCalledWith( + "Telegram accepted 80 commands after BOT_COMMANDS_TOO_MUCH (started with 100; omitted 20). Reduce plugin/skill/custom commands to expose more menu entries.", + ); + expect(runtimeError).not.toHaveBeenCalled(); }); }); diff --git a/src/telegram/bot-native-command-menu.ts b/src/telegram/bot-native-command-menu.ts index 29f3465743f..6dd8f1ba30a 100644 --- a/src/telegram/bot-native-command-menu.ts +++ b/src/telegram/bot-native-command-menu.ts @@ -50,6 +50,18 @@ function isBotCommandsTooMuchError(err: unknown): boolean { return false; } +function formatTelegramCommandRetrySuccessLog(params: { + initialCount: number; + acceptedCount: number; +}): string { + const omittedCount = Math.max(0, params.initialCount - params.acceptedCount); + return ( + `Telegram accepted ${params.acceptedCount} commands after BOT_COMMANDS_TOO_MUCH ` + + `(started with ${params.initialCount}; omitted ${omittedCount}). ` + + "Reduce plugin/skill/custom commands to expose more menu entries." + ); +} + export function buildPluginTelegramMenuCommands(params: { specs: TelegramPluginCommandSpec[]; existingCommands: Set; @@ -196,13 +208,23 @@ export function syncTelegramMenuCommands(params: { } let retryCommands = commandsToRegister; + const initialCommandCount = commandsToRegister.length; while (retryCommands.length > 0) { try { await withTelegramApiErrorLogging({ operation: "setMyCommands", runtime, + shouldLog: (err) => !isBotCommandsTooMuchError(err), fn: () => bot.api.setMyCommands(retryCommands), }); + if (retryCommands.length < initialCommandCount) { + runtime.log?.( + formatTelegramCommandRetrySuccessLog({ + initialCount: initialCommandCount, + acceptedCount: retryCommands.length, + }), + ); + } await writeCachedCommandHash(accountId, botIdentity, currentHash); return; } catch (err) {