Skip to content

fix(gateway): use correct root_id for Mattermost thread replies - #6617

Closed
nericervin wants to merge 1 commit into
NousResearch:mainfrom
waikiservicios:fix/mattermost-thread-root-id
Closed

fix(gateway): use correct root_id for Mattermost thread replies#6617
nericervin wants to merge 1 commit into
NousResearch:mainfrom
waikiservicios:fix/mattermost-thread-root-id

Conversation

@nericervin

Copy link
Copy Markdown
Contributor

Summary

Fixes Mattermost thread replies failing with root_id.app_error (400) when MATTERMOST_REPLY_MODE=thread is enabled.

Problem

When a user messages the bot inside an existing Mattermost thread, reply_to is set to event.message_id — the ID of the individual reply post. But Mattermost requires root_id to be the first post that started the thread. Using a non-root post ID causes:

{"id":"api.post.create_post.root_id.app_error","message":"Invalid RootId parameter","status_code":400}

Fix

In send(), _download_and_post_file(), and _send_local_file(): prefer metadata.thread_id (which base.py already populates from event.source.thread_id, i.e. the actual thread root) over reply_to. This handles both cases:

  • New thread (message in channel): no thread_id in metadata → falls back to reply_to, creating a new thread under the user's message
  • Existing thread (reply in thread): thread_id is the root post → reply lands in the correct thread

Test plan

  • Send a message in a channel with MATTERMOST_REPLY_MODE=thread → bot creates a new thread (reply under user's message)
  • Reply to the bot inside that thread → bot replies in the same thread (no 400 error)
  • Send a DM → bot responds normally (no thread behavior)
  • Send an image/file in a thread → attachment lands in the correct thread

When replying inside an existing Mattermost thread, Hermes was using
event.message_id (the individual reply post) as root_id. Mattermost
requires root_id to be the first post that started the thread, so
replies to threaded messages failed with root_id.app_error (400).

Now prefer metadata.thread_id (the actual thread root) over reply_to
when available. This correctly handles both cases:
- New thread: reply_to (user's message) becomes the thread root
- Existing thread: metadata.thread_id points to the original root
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery labels Apr 29, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #12063 — same underlying issue (Mattermost adapter ignoring metadata.thread_id). Also see #9731 (sticky thread routing).

1 similar comment
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #12063 — same underlying issue (Mattermost adapter ignoring metadata.thread_id). Also see #9731 (sticky thread routing).

@randomsnowflake

Copy link
Copy Markdown

Also related to #18279 (only one paralell threaded mattermost conversation possible)

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused Mattermost thread-root fix. This is already implemented on current main.

  • Automated hermes-sweeper review verified that 06161c6ed resolves a reply post to its Mattermost root before assigning payload["root_id"]; the implementation now lives at plugins/platforms/mattermost/adapter.py:326-340 and is used for text sends at :363-365.
  • The same resolved-root behavior covers URL and local file attachments at plugins/platforms/mattermost/adapter.py:545-549 and :586-590.
  • tests/gateway/test_mattermost.py:361-375 verifies metadata thread-root delivery.
  • The fix shipped in v2026.5.28; the Mattermost adapter was subsequently migrated from the PR's former path to the bundled plugin in af973e407.

Closing as implemented on main.

@teknium1 teknium1 closed this Jul 12, 2026
@teknium1 teknium1 added sweeper:implemented-on-main Sweeper: behavior already present on current main sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 12, 2026
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 sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:implemented-on-main Sweeper: behavior already present on current main sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants