fix: quiet Telegram command overflow retry logs

This commit is contained in:
Peter Steinberger 2026-03-13 01:45:47 +00:00
parent de3e6a8c5b
commit ddeb423944
6 changed files with 54 additions and 25 deletions

View File

@ -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.

View File

@ -335,9 +335,10 @@ curl "https://api.telegram.org/bot<bot_token>/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`
</Accordion>

View File

@ -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)

View File

@ -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).

View File

@ -13,6 +13,7 @@ type SyncMenuOptions = {
accountId: string;
botIdentity: string;
runtimeLog?: ReturnType<typeof vi.fn>;
runtimeError?: ReturnType<typeof vi.fn>;
};
function syncMenuCommandsWithMocks(options: SyncMenuOptions): void {
@ -22,7 +23,7 @@ function syncMenuCommandsWithMocks(options: SyncMenuOptions): void {
} as unknown as Parameters<typeof syncTelegramMenuCommands>[0]["bot"],
runtime: {
log: options.runtimeLog ?? vi.fn(),
error: vi.fn(),
error: options.runtimeError ?? vi.fn(),
exit: vi.fn(),
} as Parameters<typeof syncTelegramMenuCommands>[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<typeof syncTelegramMenuCommands>[0]["bot"],
runtime: {
log: runtimeLog,
error: vi.fn(),
exit: vi.fn(),
} as Parameters<typeof syncTelegramMenuCommands>[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();
});
});

View File

@ -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<string>;
@ -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) {