fix(telegram): omit message_thread_id for private chats to prevent silent message drops#17433
Conversation
src/telegram/send.ts
Outdated
| // @-usernames always resolve to private chats or channels; treat as dm. | ||
| if (trimmed.startsWith("@")) { | ||
| return "dm"; |
There was a problem hiding this comment.
@-usernames can also be public groups/supergroups
The comment says "@-usernames always resolve to private chats or channels" but in Telegram, @-usernames can also refer to public supergroups — which can have forum topics enabled. If someone sends to a public forum group via @groupname with a messageThreadId, this would incorrectly classify it as "dm" and suppress the message_thread_id.
In practice this is unlikely to cause issues since the main outbound path uses numeric chat IDs from session routing (negative for groups), and normalizeChatId only produces @-prefixed values for manual/CLI sends. But the comment is misleading and this could become a subtle bug if the code path is used differently in the future.
Consider updating the comment to acknowledge this limitation, or handling this case if public forum groups addressed by username is a supported use case.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/send.ts
Line: 174:176
Comment:
**`@`-usernames can also be public groups/supergroups**
The comment says "`@`-usernames always resolve to private chats or channels" but in Telegram, `@`-usernames can also refer to public supergroups — which *can* have forum topics enabled. If someone sends to a public forum group via `@groupname` with a `messageThreadId`, this would incorrectly classify it as `"dm"` and suppress the `message_thread_id`.
In practice this is unlikely to cause issues since the main outbound path uses numeric chat IDs from session routing (negative for groups), and `normalizeChatId` only produces `@`-prefixed values for manual/CLI sends. But the comment is misleading and this could become a subtle bug if the code path is used differently in the future.
Consider updating the comment to acknowledge this limitation, or handling this case if public forum groups addressed by username is a supported use case.
How can I resolve this? If you propose a fix, please make it concise.7154157 to
6ec4fe6
Compare
The 'rejects default OpenClaw state per-agent workspace-* roots' test fails in CI because the test harness sets HOME to a temp directory under os.tmpdir() (e.g. /tmp/openclaw-test-home-xC06Jb). Since os.tmpdir() (/tmp) is a default allowed media root, ALL paths under the test HOME directory match the tmpdir root, causing the test to resolve instead of reject. Fix: pin OPENCLAW_STATE_DIR to an absolute path outside /tmp (/var/openclaw-guard-reject-test) for the duration of the test, ensuring no default root accidentally matches the workspace-* path. This is the same pattern steipete used in be9b5ce for the 'web media loading' describe block, but was missing from the separate 'local media root guard' describe block.
…lent message drops The outbound send functions in send.ts hardcode scope: 'forum' when constructing the TelegramThreadSpec for message_thread_id, regardless of chat type. Private chats (positive numeric chatId) don't support forum topics, so Telegram rejects the API call with 400 'message thread not found', silently dropping the message. Add an inferThreadScope() helper that determines the thread scope from the chatId: - Positive numeric IDs and @-usernames → 'dm' (private chat) - Negative numeric IDs → 'forum' (group/supergroup) This allows the existing buildTelegramThreadParams() guard (which already filters scope='dm') to properly omit message_thread_id for private chats. All three outbound send paths are fixed: - sendMessageTelegram (text + media) - sendStickerTelegram - sendPollTelegram Tests updated to use negative chatIds for forum retry tests, and a new test added to verify private chats never include message_thread_id. Fixes openclaw#17242
6ec4fe6 to
5c5de82
Compare
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:34.771Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:34.776Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:34.778Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:34.778Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=true (env:OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:34.779Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:34.779Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=true (config)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:34.781Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:34.781Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (env:OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:34.781Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:34.782Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.090Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.095Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.092Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.095Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.092Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.097Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.092Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.097Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: can't parse entities: Can't find end of the entity","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.106Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.106Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: can't parse entities: Can't find end of the entity starting at byte offset 9","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.109Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.109Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: can't parse entities: Can't find end of the entity starting at byte offset 9","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.114Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.114Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: chat not found","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.119Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.119Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: chat not found","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.122Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.122Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: chat not found","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.125Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.126Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.127Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.127Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: message thread not found","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.136Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.136Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram message failed: 400: Bad Request: message thread not found","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.139Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.139Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram photo failed: 400: Bad Request: message thread not found","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:36.149Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:36.149Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:37.005Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:37.008Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram editMessage failed: 400: Bad Request: can't parse entities","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:37.018Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:37.018Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.936Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.939Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.945Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.948Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.945Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.949Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.949Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.952Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.954Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.958Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.953Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.960Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.954Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.960Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.957Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.962Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.958Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.966Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:39.980Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:39.984Z"} | ||
| {"0":"{\"module\":\"telegram-auto-reply\"}","1":{"chatId":"1234","senderUserId":"999","username":"random","matchKey":"none","matchSource":"none"},"2":"telegram pairing request","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"module\":\"telegram-auto-reply\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:40.000Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/telegram/bot-message-context.ts:283:22","fileName":"bot-message-context.ts","fileNameWithLine":"bot-message-context.ts:283","fileColumn":"22","fileLine":"283","filePath":"src/telegram/bot-message-context.ts","filePathWithLine":"src/telegram/bot-message-context.ts:283","method":"buildTelegramMessageContext"}},"time":"2026-02-15T19:17:40.002Z"} | ||
| {"0":"{\"module\":\"telegram-auto-reply\"}","1":{"chatId":"1234","senderUserId":"999","username":"random","matchKey":"none","matchSource":"none"},"2":"telegram pairing request","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"module\":\"telegram-auto-reply\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:40.004Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/telegram/bot-message-context.ts:283:22","fileName":"bot-message-context.ts","fileNameWithLine":"bot-message-context.ts:283","fileColumn":"22","fileLine":"283","filePath":"src/telegram/bot-message-context.ts","filePathWithLine":"src/telegram/bot-message-context.ts:283","method":"buildTelegramMessageContext"}},"time":"2026-02-15T19:17:40.005Z"} | ||
| {"0":"{\"module\":\"telegram-auto-reply\"}","1":{"chatId":7,"reason":"no-mention"},"2":"skipping group message","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"module\":\"telegram-auto-reply\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:40.010Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/telegram/bot-message-context.ts:486:14","fileName":"bot-message-context.ts","fileNameWithLine":"bot-message-context.ts:486","fileColumn":"14","fileLine":"486","filePath":"src/telegram/bot-message-context.ts","filePathWithLine":"src/telegram/bot-message-context.ts:486","method":"buildTelegramMessageContext"}},"time":"2026-02-15T19:17:40.013Z"} | ||
| {"0":"{\"module\":\"telegram-auto-reply\"}","1":{"chatId":456,"title":"Ops","reason":"not-allowed"},"2":"skipping group message","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"module\":\"telegram-auto-reply\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:40.017Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/telegram/bot-handlers.ts:787:18","fileName":"bot-handlers.ts","fileNameWithLine":"bot-handlers.ts:787","fileColumn":"18","fileLine":"787","filePath":"src/telegram/bot-handlers.ts","filePathWithLine":"src/telegram/bot-handlers.ts:787"}},"time":"2026-02-15T19:17:40.019Z"} | ||
| {"0":"{\"module\":\"telegram-auto-reply\"}","1":{"chatId":123,"reason":"no-mention"},"2":"skipping group message","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"module\":\"telegram-auto-reply\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:40.021Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/telegram/bot-message-context.ts:486:14","fileName":"bot-message-context.ts","fileNameWithLine":"bot-message-context.ts:486","fileColumn":"14","fileLine":"486","filePath":"src/telegram/bot-message-context.ts","filePathWithLine":"src/telegram/bot-message-context.ts:486","method":"buildTelegramMessageContext"}},"time":"2026-02-15T19:17:40.022Z"} | ||
| {"0":"{\"subsystem\":\"telegram/network\"}","1":"telegram: autoSelectFamily=false (default-node22)","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/network\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:40.531Z","logLevelId":3,"logLevelName":"INFO","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:40.534Z"} | ||
| {"0":"{\"subsystem\":\"telegram/api\"}","1":"telegram poll failed: 400: Bad Request: message thread not found","_meta":{"runtime":"node","runtimeVersion":"22.22.0","hostname":"unknown","name":"{\"subsystem\":\"telegram/api\"}","parentNames":["openclaw"],"date":"2026-02-15T19:17:40.537Z","logLevelId":5,"logLevelName":"ERROR","path":{"fullFilePath":"/tmp/openclaw/src/logging/subsystem.ts:226:12","fileName":"subsystem.ts","fileNameWithLine":"subsystem.ts:226","fileColumn":"12","fileLine":"226","filePath":"src/logging/subsystem.ts","filePathWithLine":"src/logging/subsystem.ts:226","method":"logToFile"}},"time":"2026-02-15T19:17:40.538Z"} |
There was a problem hiding this comment.
Accidentally committed log file
This test log file appears to have been committed by accident. It contains runtime log output (Telegram API errors, network config, pairing requests) that shouldn't be tracked in version control. Please remove this file from the commit.
Prompt To Fix With AI
This is a comment left during a code review.
Path: openclaw-2026-02-15.log
Line: 1:38
Comment:
**Accidentally committed log file**
This test log file appears to have been committed by accident. It contains runtime log output (Telegram API errors, network config, pairing requests) that shouldn't be tracked in version control. Please remove this file from the commit.
How can I resolve this? If you propose a fix, please make it concise.|
Private chats with bots do support forum topics since Bot API 9.3 (December 31, 2025). The This exact pattern has already broken DM topics 3 times in the last 3 weeks (commits The correct approach: check |
|
You're absolutely right — thanks for the thorough review. I wasn't aware that Bot API 9.3 added forum topic support for private chats via The correct fix should check Thanks for linking #18974 — helpful to see the full timeline of this recurring issue. |
|
Closing per Lukavyi's feedback. The |
fix(telegram): omit message_thread_id for private chats
Fixes #17242
Problem
When delivering messages to Telegram private chats, the outbound send functions hardcode
scope: 'forum'in the thread spec:Private chats (positive chatId) don't support forum topics. Telegram rejects the API call with
400: Bad Request: message thread not found, and the message is silently dropped — the user sees blue checkmarks but the agent never receives/sends the message.From the bug report: 111 failures over 4 days (81 on Feb 11 alone).
Root Cause
sendMessageTelegram,sendStickerTelegram, andsendPollTelegramall construct the thread spec withscope: 'forum'regardless of whether the chat is a private chat or a group. The existingbuildTelegramThreadParams()helper already correctly filters outscope: 'dm', but it never seesscope: 'dm'because the callers always pass'forum'.Fix
Add
inferThreadScope(chatId)helper that determines scope from the chatId:'dm'(private chat)@-usernames →'dm'(private chat / channel)'forum'(group/supergroup, may be forum)This lets the existing
buildTelegramThreadParams()guard properly omitmessage_thread_idfor private chats.Changed Files
src/telegram/send.tsinferThreadScope(); fix all 3 send functionssrc/telegram/send.returns-undefined-empty-input.test.tssrc/telegram/send.poll.test.tsTesting
omits message_thread_id for private chats (positive chatId)Greptile Summary
Fixes silent message drops when sending to Telegram private chats by adding
inferThreadScope(chatId)to correctly determine whethermessage_thread_idshould be included in API calls. Private chats (positive numeric IDs) getscope: "dm", which causes the existingbuildTelegramThreadParams()guard to omitmessage_thread_id— preventing the Telegram 400 "message thread not found" error.inferThreadScope()helper insrc/telegram/send.tsand applies it consistently to all three send functions (sendMessageTelegram,sendStickerTelegram,sendPollTelegram)message_thread_idat allmessage_thread_idis omitted for private chatssrc/web/media.test.ts(tmpdir HOME overlap)openclaw-2026-02-15.log— a test log file was accidentally committed and should be removedConfidence Score: 4/5
inferThreadScopefix is straightforward, integrates cleanly with the existingbuildTelegramThreadParams()guard, and is applied consistently to all three send functions. Tests are updated appropriately. Score is 4 instead of 5 solely because an unrelated log file (openclaw-2026-02-15.log) was accidentally committed.openclaw-2026-02-15.logshould be removed from the commit — it's an accidentally committed test log file.Last reviewed commit: 5c5de82