Skip to content

fix(gateway/telegram): route /model picker thread_id through helper#22383

Closed
Matthieu-C wants to merge 1 commit into
NousResearch:mainfrom
Matthieu-C:fix/telegram-model-picker-general-topic
Closed

fix(gateway/telegram): route /model picker thread_id through helper#22383
Matthieu-C wants to merge 1 commit into
NousResearch:mainfrom
Matthieu-C:fix/telegram-model-picker-general-topic

Conversation

@Matthieu-C

Copy link
Copy Markdown

Problem

In any Telegram forum group's General topic, /model silently falls back
to a plain-text model list instead of rendering the inline-keyboard picker.
This has been the recurring "after every hermes update /model breaks again"
bug — local post-update patches kept getting wiped because the fix never
landed upstream.

gateway.log confirms the failure mode:

WARNING gateway.platforms.telegram: [Telegram] send_model_picker failed: Message thread not found

Root Cause

TelegramAdapter.send_model_picker was the last sender in
gateway/platforms/telegram.py that bypassed _message_thread_id_for_send.
It computed:

message_thread_id=int(thread_id) if thread_id else None

The forum General topic surfaces in metadata as thread_id="1", a synthetic
id Hermes uses to scope events to that topic. Telegram's sendMessage
rejects message_thread_id=1 with BadRequest('Message thread not found') — the helper exists precisely to map "1"None for sends.
Every other _bot.send_* call in this file already routes through it; the
picker was the last hold-out. The exception was caught, a warning was
logged, the picker reported success=False, and gateway/run.py fell
through to its plain-text fallback.

Fix

Route send_model_picker's thread_id through _message_thread_id_for_send
like every other send path, and add the standard "thread not found"
single-retry without message_thread_id so transient topic-disappearance
still delivers the picker (mirrors the contract of send() and the other
auxiliary methods).

Tests

Adds tests/gateway/test_telegram_model_picker_thread.py with 4 cases:

  1. General-topic collapsemetadata={"thread_id": "1"} must send with
    message_thread_id=None. This is the regression guard for the original bug.
  2. Real-topic pass-through"17585" must reach Telegram as 17585.
  3. Thread-not-found retry — when a real thread disappears mid-conversation,
    retry once without message_thread_id and still succeed.
  4. No metadata — DM/non-forum-group path unchanged.
$ pytest tests/gateway/test_telegram_model_picker_thread.py tests/gateway/test_telegram_thread_fallback.py tests/gateway/test_dm_topics.py -q
46 passed in 5.20s

Audit

grep -n "message_thread_id=int" gateway/platforms/telegram.py now returns a
single hit at line 729 — edit_forum_topic, where int(thread_id) is
correct (renaming a topic genuinely needs the topic id, including 1).

Every other _bot.send_* call routes through _message_thread_id_for_send,
matching the invariant documented in
software-development/debugging-hermes-tui-commands/references/gateway-interactive-pickers.md.

send_model_picker was the last sender in telegram.py that bypassed
_message_thread_id_for_send. In a forum group's General topic the helper
maps the synthetic thread id "1" to None because Telegram's sendMessage
rejects message_thread_id=1 with BadRequest('Message thread not found').
The picker instead passed int("1")=1, the API rejected it, the gateway
swallowed the error, and the user saw the plain-text fallback instead of
the inline-keyboard picker.

Fix: route through _message_thread_id_for_send like every other send
path, plus add the standard 'thread not found' single-retry without
message_thread_id so transient topic-disappearance still delivers the
picker.

Adds regression tests in tests/gateway/test_telegram_model_picker_thread.py
covering General-topic id collapse, real-topic pass-through, thread-not-found
retry, and the no-metadata path.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter labels May 9, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #19961 (and #12873, #18612). Same fix: route send_model_picker thread_id through _message_thread_id_for_send(). Multiple competing PRs exist for the same one-line fix.

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Thanks for catching this — the General-topic mapping (message_thread_id="1"None) you proposed for send_model_picker is now on main. It landed via #22410 (salvage of @leehack's #22053 telegram DM topic fix), which routed send_model_picker through _thread_kwargs_for_send — a strict superset of the _message_thread_id_for_send mapping you proposed. That helper now handles both forum General topics (your case) AND Hermes-created DM topic lanes that #22053 was originally about.

The parallel code path in the send_message tool's standalone _send_telegram helper had the same bug — fixed in #22423 just now (Fixes #22267).

Closing as superseded — thanks for the contribution and for keeping us focused on this bug class!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/telegram Telegram bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants