Skip to content

Telegram: message tool sends stale message_thread_id in DM chats, causing 'message thread not found' error #15662

@billyclawson

Description

@billyclawson

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

  1. User sends a message that is a reply to a bot message in a DM chat
  2. OpenClaw caches threadId (the replied-to message ID) in deliveryContext of the session
  3. Agent uses message tool to send a proactive message to the same chat
  4. 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:

  1. Add the same sendWithThreadFallback retry logic to the proactive message tool send path
  2. Do not cache threadId in deliveryContext for non-forum DM chats
  3. Both (defense in depth)

Metadata

Metadata

Assignees

No one assigned

    Labels

    close:duplicateClosed as duplicatededupe:childDuplicate issue/PR child in dedupe clusterstaleMarked as stale due to inactivity

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions