#12936: fix(telegram): omit message_thread_id for private DM chats
channel: telegram
size: S
Cluster:
Messaging Platform Improvements
## Summary
Fixes Telegram proactive sends (cron delivery, message tool) failing with `400: message thread not found` when targeting private DM chats.
## Problem
OpenClaw stores `message_thread_id` from inbound Telegram messages as `lastThreadId`. When sending proactively to a private DM, this thread ID gets passed to the Telegram API — but private chats do not support `message_thread_id`, causing a 400 error.
## Changes
**`src/telegram/bot/helpers.ts`**
- `buildTelegramThreadParams()` now returns `undefined` when `scope === "dm"`, preventing `message_thread_id` from being included in API calls to private chats
**`src/telegram/bot/helpers.test.ts`**
- Updated test to verify DM thread IDs are omitted (previously tested the buggy behavior)
- Added coverage for multiple DM thread ID values
**`src/telegram/bot/delivery.test.ts`**
- Updated delivery test to verify `message_thread_id` is NOT included when thread scope is `dm`
## Testing
- All 24 helper tests pass ✅
- All 10 delivery tests pass ✅
- All 9 DM thread/dispatch tests pass ✅
- `pnpm exec vitest run src/telegram/` — all Telegram tests green
## Notes
- 🤖 AI-assisted (Claude) — fully tested, all changes understood
- The `send.ts` path already had a `sendWithThreadFallback` retry mechanism; this fix prevents the error at the source in the `delivery.ts` path
Closes #12929
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR changes `buildTelegramThreadParams()` to return `undefined` for `scope: "dm"`, preventing `message_thread_id` from being sent to Telegram private chats (which can fail with `400: message thread not found`). Tests in `src/telegram/bot/helpers.test.ts` and `src/telegram/bot/delivery.test.ts` are updated to assert DM sends omit `message_thread_id`.
One integration surface remains inconsistent: `createTelegramDraftStream` uses `buildTelegramThreadParams` and will now omit DM thread params, but `src/telegram/draft-stream.test.ts` still expects DM drafts to include `message_thread_id`. That test (or the draft-stream behavior) needs to be updated for the PR’s new contract to be consistent across send paths.
<h3>Confidence Score: 3/5</h3>
- This PR is close to mergeable but has a cross-file test/behavior mismatch that needs to be resolved.
- Core change is small and well-tested in the modified files, but the new DM behavior in `buildTelegramThreadParams` conflicts with existing expectations in the telegram draft stream tests, indicating an unaddressed integration update that will break CI or leave inconsistent behavior.
- src/telegram/draft-stream.test.ts (and confirm intended behavior in src/telegram/draft-stream.ts)
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#7261: fix(telegram): preserve DM topic thread id for outbound media
by ViffyGwaanl · 2026-02-02
90.3%
#14443: fix(telegram): skip General topic thread ID for all chat types (#14...
by lailoo · 2026-02-12
90.0%
#17968: fix(telegram): restore DM topic thread ids with send-path fallback
by Leonccaa · 2026-02-16
87.6%
#19213: Telegram: preserve DM topic thread in direct replies
by Kemalau · 2026-02-17
87.0%
#17952: fix(telegram): support message_thread_id for DM topics
by timbrinded · 2026-02-16
87.0%
#19050: fix(telegram): skip message_thread_id for private chats to prevent ...
by Limitless2023 · 2026-02-17
86.1%
#3368: fix: sessions navigation, DM thread display, and DM thread delivery...
by Lukavyi · 2026-01-28
85.5%
#17953: fix(telegram): prevent silent message loss and duplicate messages i...
by zuyan9 · 2026-02-16
84.6%
#6192: Telegram: fix DM Topics thread routing
by ViffyGwaanl · 2026-02-01
83.1%
#16548: fix(telegram): enhance chat_id validation and diagnostics
by tanujbhaud · 2026-02-14
82.9%