Bug Description
The message tool (proactive send path) fails with 400: Bad Request: message thread not found when sending to a Telegram DM chat. This happens because a threadId gets cached in the session deliveryContext from Telegram reply chains, then gets passed as message_thread_id on subsequent proactive sends — but DM chats do not support forum topics, so Telegram rejects it.
Steps to Reproduce
- User sends a message that is a reply to a bot message in a DM chat
- OpenClaw caches
threadId (the replied-to message ID) in deliveryContext of the session
- Agent uses
message tool to send a proactive message to the same chat
- Telegram API returns
400: Bad Request: message thread not found
Expected Behavior
message_thread_id should not be sent for DM chats (only for forum/topic groups)
- OR the proactive send path should have the same retry-without-thread fallback that the inline reply path already has
Current Behavior
deliveryContext.threadId gets set from reply chains in DMs
- The
message tool includes this as message_thread_id in the Telegram API call
- Telegram rejects it for non-forum chats
- No retry-without-thread fallback on this code path
Analysis
Looking at the source (reply-DptDUVRg.js), the inline reply path already has a fallback:
if (!hasMessageThreadIdParam(params) || !isTelegramThreadNotFoundError(err)) throw err;
console.warn(`telegram ${label} failed with message_thread_id, retrying without thread`);
return await attempt(removeMessageThreadIdParam(params), `${label}-threadless`);
But the proactive message tool send path does not appear to have this same fallback.
Additionally, resolveTelegramAutoThreadId reads from context.currentThreadTs which comes from the cached deliveryContext.threadId — this should probably check whether the chat is a forum/group before using it.
Workaround Attempted
- Manually editing
sessions.json to remove threadId from deliveryContext — does not persist because in-memory state overwrites the file on restart
- Stopping gateway, editing file, restarting — threadId gets re-cached from the next incoming message
Environment
- OpenClaw version: 2026.2.6-3 (CLI 2026.2.9)
- Channel: Telegram DM (not a forum/topic group)
- Chat ID: private DM
- Cached threadId: 7078 (a message_id from a reply chain)
Suggested Fix
Either:
- Add the same
sendWithThreadFallback retry logic to the proactive message tool send path
- Do not cache
threadId in deliveryContext for non-forum DM chats
- Both (defense in depth)
Bug Description
The
messagetool (proactive send path) fails with400: Bad Request: message thread not foundwhen sending to a Telegram DM chat. This happens because athreadIdgets cached in the sessiondeliveryContextfrom Telegram reply chains, then gets passed asmessage_thread_idon subsequent proactive sends — but DM chats do not support forum topics, so Telegram rejects it.Steps to Reproduce
threadId(the replied-to message ID) indeliveryContextof the sessionmessagetool to send a proactive message to the same chat400: Bad Request: message thread not foundExpected Behavior
message_thread_idshould not be sent for DM chats (only for forum/topic groups)Current Behavior
deliveryContext.threadIdgets set from reply chains in DMsmessagetool includes this asmessage_thread_idin the Telegram API callAnalysis
Looking at the source (
reply-DptDUVRg.js), the inline reply path already has a fallback:But the proactive
messagetool send path does not appear to have this same fallback.Additionally,
resolveTelegramAutoThreadIdreads fromcontext.currentThreadTswhich comes from the cacheddeliveryContext.threadId— this should probably check whether the chat is a forum/group before using it.Workaround Attempted
sessions.jsonto removethreadIdfromdeliveryContext— does not persist because in-memory state overwrites the file on restartEnvironment
Suggested Fix
Either:
sendWithThreadFallbackretry logic to the proactive message tool send paththreadIdindeliveryContextfor non-forum DM chats