fix(discord): skip history backfill when channel lacks .history#26301
fix(discord): skip history backfill when channel lacks .history#26301briandevans wants to merge 1 commit into
.history#26301Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR prevents Discord channel context backfill from raising when a “channel-like” object doesn’t implement history, and adds a regression test to lock in the behavior.
Changes:
- Add an early return in
_fetch_channel_contextwhenchannel.historyis missing. - Add an async regression test covering channel objects without
history.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tests/gateway/test_discord_free_response.py | Adds a regression test ensuring missing history returns empty context instead of raising. |
| gateway/platforms/discord.py | Guards _fetch_channel_context against channel objects that lack history. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # channels, voice channels, and custom proxies in tests can lack it. | ||
| # Skip rather than raise: the outer ``except`` swallows ``discord.Forbidden`` | ||
| # only when ``discord`` is the real library, so an AttributeError that | ||
| # leaks past would surface as a TypeError under mocked-discord test | ||
| # setups (the except clause can't evaluate a MagicMock as an exception). | ||
| if not hasattr(channel, "history"): |
|
CI audit — all 3
Reproduces locally on clean |
7ba870f to
53e43d3
Compare
4e46359 to
07edd4a
Compare
The new `_fetch_channel_context` path added by 4abfb6b calls `channel.history(...)` unconditionally. Channel-like objects that do not implement history — Forum parent channels, voice channels in some deployments, and custom proxies in tests — raise AttributeError. The outer `except discord.Forbidden:` cannot catch it: under mocked-discord test setups (e.g. tests/e2e/test_discord_adapter.py), `discord` is a MagicMock and evaluating `discord.Forbidden` as an exception class raises `TypeError: catching classes that do not inherit from BaseException is not allowed`, which masks the original error and bubbles up. Symptom: 4 e2e tests in `tests/e2e/test_discord_adapter.py` started failing on every PR after 4abfb6b landed: test_mention_then_command test_nickname_mention_then_command test_text_before_command_not_detected test_command_detected_after_auto_thread The fix is a defensive guard: if the channel does not expose `history`, silently return an empty backfill string. This is the same end state as any successful backfill that yields zero usable messages. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
07edd4a to
934a3c0
Compare
|
Closing to focus the queue on security/file-safety work where civilian merges are landing. Happy to reopen if maintainers want this picked up. |
What does this PR do?
Adds a defensive
hasattr(channel, "history")guard at the start of_fetch_channel_contextingateway/platforms/discord.py. Restores 4 e2e tests intests/e2e/test_discord_adapter.pythat have been failing on every open PR since commit4abfb6bc2(feat(discord): default history backfill on, expand to per-user + threads). Adds a focused regression test intests/gateway/test_discord_free_response.py.Root cause: the
_handle_messagepath added by4abfb6bc2unconditionally calls_fetch_channel_contextfor non-DM channels, which jumps straight intoasync for msg in channel.history(...). Channel-like objects that don't implementhistory— Forum parent channels, voice channels in some deployments, and theSimpleNamespacechannel proxies used bytests/e2e/test_discord_adapter.py— raiseAttributeError. The outerexcept discord.Forbidden:atgateway/platforms/discord.py:3730cannot catch it cleanly: under mocked-discord test setupsdiscordis aMagicMock, so Python evaluatesdiscord.Forbiddenas the except class before matching, which raisesTypeError: catching classes that do not inherit from BaseException is not allowed. ThatTypeErrorthen masks the originalAttributeErrorand bubbles past the broaderexcept Exceptionhandler.Related Issue
Follow-up to commit
4abfb6bc2. No standalone bug issue — surfaced as 4 e2e regressions on every open PR.Type of Change
Changes Made
gateway/platforms/discord.py— early return""from_fetch_channel_contextwhen the channel doesn't exposehistory. Same end state as a real fetch that yielded zero usable messages.tests/gateway/test_discord_free_response.py— newtest_fetch_channel_context_returns_empty_when_channel_lacks_historycovering a bareSimpleNamespacechannel, asserting empty-string return and no exception.How to Test
uv run --with pytest --with pytest-xdist --with pytest-asyncio python3 -m pytest tests/gateway/test_discord_free_response.py tests/e2e/test_discord_adapter.py -vTypeError: catching classes that do not inherit from BaseException is not allowedfrom CI logs. Restore the fix — all 6_fetch_channel_contextunit tests pass.The 4 previously-failing e2e tests now restored:
TestMentionStrippedCommandDispatch::test_mention_then_commandTestMentionStrippedCommandDispatch::test_nickname_mention_then_commandTestMentionStrippedCommandDispatch::test_text_before_command_not_detectedTestAutoThreadingPreservesCommand::test_command_detected_after_auto_threadChecklist
Code
fix(scope):,feat(scope):, etc.)Documentation & Housekeeping
docs/, docstrings) — N/Acli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/ARelated / Positioning
4abfb6bc2(feat(discord): default history backfill on, expand to per-user + threads)._fetch_channel_contextorchannel.history(verified viagh search prs).