Discord thread history backfill decoupling fixes
Cluster 33666. Data as of
Nothing open on GitHub. Fix merged in #33827 on 28 May 2026. Check it covers your case.
The short answer
- Known?
- Yes. 4 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #33827. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #33827. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and pull requests address a bug where Discord thread history backfill was being skipped or incorrectly gated by mention or bot-thread conditions. The work involves decoupling backfill logic from mention requirements and related gateway context handling.
Open issues0
Open PRs0
Fixes on record
-
#33827 fix(discord): decouple thread history backfill from mention gating
files:
plugins/platforms/discord/adapter.py,scripts/release.py,tests/gateway/test_discord_free_response.py,tests/gateway/test_discord_slash_commands.pyShow the diff
-
plugins/platforms/discord/adapter.py@@ -4811,14 +4811,19 @@ async def _handle_message(self, message: DiscordMessage) -> None: # to keep the partition rule clean. _channel_context = None _is_dm = isinstance(message.channel, discord.DMChannel) - if not _is_dm: - _needed_mention = ( - require_mention - and not is_free_channel - and not in_bot_thread - ) - _backfill_enabled = self._discord_history_backfill() - if _needed_mention and _backfill_enabled: + if not _is_dm and self._discord_history_backfill(): + # Run backfill when there's a real gap to fill: + # - mention-gated channels with no free-response override + # (messages between bot turns aren't in the transcript) + # - any thread (in_bot_thread bypasses the mention check, but + # processing-window gaps and post-restart context still need + # recovery) + # DMs skip entirely because every DM message triggers the bot, + # so the session transcript already has everything. + # Auto-threaded messages also skip — we just created the thread, + # there's nothing prior to backfill. + _has_mention_gap = require_mention and not is_free_channel and not in_bot_thread + if (_has_mention_gap or is_thread) and auto_threaded_channel is None: _backfill_text = await self._fetch_channel_context( message.channel, before=message, ) -
scripts/release.py@@ -52,6 +52,7 @@ "[email protected]": "superearn-fisher", "[email protected]": "kpadilha", "[email protected]": "chaconne67", + "[email protected]": "Pluviobyte", "[redacted:email]": "sanghyuk-seo-nexcube", "[redacted:email]": "Brixyy", "[redacted:email]": "wangpuv", -
tests/gateway/test_discord_free_response.py@@ -851,6 +851,27 @@ async def test_discord_per_user_channel_backfills_too(adapter, monkeypatch): assert event.channel_context == "[Recent channel messages]\n[Alice] context" [redacted:email] +async def test_discord_participated_thread_backfills_without_mention(adapter, monkeypatch): + """Known threads still need recent thread context when mention gating is bypassed.""" + monkeypatch.setenv("DISCORD_REQUIRE_MENTION", "true") + monkeypatch.delenv("DISCORD_FREE_RESPONSE_CHANNELS", raising=False) + monkeypatch.delenv("DISCORD_THREAD_REQUIRE_MENTION", raising=False) + adapter.config.extra["history_backfill"] = True + adapter._fetch_channel_context = AsyncMock(return_value="[Recent channel messages]\n[Alice] thread context") + + thread = FakeThread(channel_id=456, name="follow-up") + adapter._threads.mark("456") + + message = make_message(channel=thread, content="follow-up without mention") + await adapter._handle_message(message) + + adapter._fetch_channel_context.assert_awaited_once() + event = adapter.handle_message.await_args.args[0] + assert event.text == "follow-up without mention" + assert event.channel_context == "[Recent channel messages]\n[Alice] thread context" + + @pytest.mark.asyncio async def test_discord_dm_does_not_backfill(adapter, monkeypatch): """DMs skip backfill — every DM triggers the bot, so there's no mention gap.""" @@ -884,3 +905,25 @@ async def test_discord_dm_does_not_backfill(adapter, monkeypatch): assert event.channel_context is None [redacted:email] +async def test_discord_auto_thread_skips_backfill(adapter, monkeypatch): + """Auto-created threads skip backfill — the thread is brand new with no prior context.""" + monkeypatch.setenv("DISCORD_REQUIRE_MENTION", "true") + monkeypatch.setenv("DISCORD_AUTO_THREAD", "true") + monkeypatch.delenv("DISCORD_NO_THREAD_CHANNELS", raising=False) + monkeypatch.delenv("DISCORD_FREE_RESPONSE_CHANNELS", raising=False) + adapter.config.extra["history_backfill"] = True + + fake_thread = FakeThread(channel_id=777, name="auto-thread") + adapter._auto_create_thread = AsyncMock(return_value=fake_thread) + adapter._fetch_channel_context = AsyncMock(return_value="[Recent channel messages]\n[Alice] noise") + + bot_user = adapter._client.user + parent = FakeTextChannel(channel_id=200, name="general") + message = make_message(channel=parent, content="hello", mentions=[bot_user]) + await adapter._handle_message(message) + + adapter._auto_create_thread.assert_awaited_once() + adapter._fetch_channel_context.assert_not_awaited() + + -
tests/gateway/test_discord_slash_commands.py@@ -624,6 +624,13 @@ def __init__(self, channel_id=100, name="general", guild_name="TestGuild"): self.guild = SimpleNamespace(name=guild_name, id=1) self.topic = None + def history(self, *args, **kwargs): + async def _empty(): + return + yield # pragma: no cover — make this an async generator + + return _empty() + class _FakeThreadChannel(_discord_mod.Thread): """isinstance(ch, discord.Thread) → True.""" @@ -636,6 +643,13 @@ def __init__(self, channel_id=200, name="existing-thread", guild_name="TestGuild self.topic = None self.parent = SimpleNamespace(id=parent_id, name="general", guild=SimpleNamespace(name=guild_name, id=1)) + def history(self, *args, **kwargs): + async def _empty(): + return + yield # pragma: no cover — make this an async generator + + return _empty() + def _fake_message(channel, *, content="Hello", author_id=42, display_name="Jezza"): return SimpleNamespace(
-
2 PRs closed without merging
From the close comments: merged via another change 2
Closed issues · 1
- Closed#33666Discord thread backfill skipped when in_bot_thread is true (thread_require_mention=false)
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.50: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Merged PRs
- #33827
- Closed issues
- 1
- Attempts
- 2 PRs closed without merging
- Fix link checked
- 28 May 2026