Skip to content

fix(discord): retry standalone send on 429 rate-limit instead of dropping chunks - #44542

Closed
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/discord-standalone-429-retry
Closed

fix(discord): retry standalone send on 429 rate-limit instead of dropping chunks#44542
liuhao1024 wants to merge 1 commit into
NousResearch:mainfrom
liuhao1024:fix/discord-standalone-429-retry

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds 429 rate-limit retry logic to the standalone Discord send path (_standalone_send), preventing multi-chunk messages from being silently truncated when a rate limit is hit mid-delivery.

Related Issue

Fixes #44468

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • plugins/platforms/discord/adapter.py: Add _standalone_parse_retry_after() helper to extract retry_after from Discord 429 JSON responses. Wrap both the text POST and per-media POST in _standalone_send with a retry loop (3 attempts, honouring retry_after with 0.5s floor and 10s cap).
  • tests/tools/test_send_message_tool.py: Add TestStandaloneParseRetryAfter (5 unit tests for the parser) and TestSendDiscord429Retry (4 integration tests covering retry-on-429, exhausted retries, missing retry_after, and non-429 error paths).

How to Test

  1. Run pytest tests/tools/test_send_message_tool.py::TestStandaloneParseRetryAfter tests/tools/test_send_message_tool.py::TestSendDiscord429Retry -v — all 9 tests should pass.
  2. Run pytest tests/tools/test_send_message_tool.py -v — all 142 tests should pass (no regressions).
  3. Run pytest tests/e2e/test_discord_adapter.py -v — all 6 tests should pass.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Code Intelligence

  • Analyzed: plugins/platforms/discord/adapter.py::_standalone_send (callers: 1 via standalone_sender_fn registry entry, flows: send_message_tool._send_to_platformentry.standalone_sender_fn)
  • Blast radius: LOW — changes are confined to the standalone send path; the live adapter path is unaffected
  • Related patterns: Mirrors the existing retry pattern in _send_telegram_message_with_retry() and the adapter's _extract_discord_retry_after() / _is_discord_rate_limit() helpers

…ping chunks

The standalone Discord send path (`_standalone_send`) returned an error
dict immediately on 429 responses with no retry.  For multi-chunk
messages sent via `hermes send`, the chunk loop in
`send_message_tool.py` aborts on the first error, silently dropping all
remaining chunks.

Discord's 429 response includes a `retry_after` field (often sub-second),
so a brief wait-and-retry delivers the full message.  The live adapter
already has retry helpers (`_extract_discord_retry_after`,
`_is_discord_rate_limit`), but the standalone path had none.

Changes:
- `plugins/platforms/discord/adapter.py`: Add `_standalone_parse_retry_after()`
  helper and retry loop (3 attempts) around both the text POST and per-media
  POST in `_standalone_send`.  Honours Discord's `retry_after` with a 0.5s
  floor and 10s cap.
- `tests/tools/test_send_message_tool.py`: Add `TestStandaloneParseRetryAfter`
  (5 tests) and `TestSendDiscord429Retry` (4 tests) covering retry-on-429,
  exhausted retries, missing retry_after, and non-429 error paths.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Summary

Verdict: Approved

Bug Fix - Looks Good

  • plugins/platforms/discord/adapter.py — Adds retry logic for 429 rate-limit responses in the standalone send path, using Discord's retry_after field (floored at 0.5s, capped at 10s, max 3 attempts).
  • Handles 429 for both text messages and media uploads.
  • Clean retry-after parsing with proper error handling.

Testing

  • tests/tools/test_send_message_tool.py — Comprehensive test coverage:
    • TestStandaloneParseRetryAfter: 5 tests for the parsing function
    • TestSendDiscord429Retry: 4 tests for the retry behavior (success, exhausted retries, no retry_after, non-429)

Code Quality

  • No security concerns.
  • Well-structured retry loop with clear logging.

Reviewed by Hermes Agent

@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/discord Discord bot adapter duplicate This issue or pull request already exists labels Jun 12, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #44488 — same Discord 429 retry (honoring retry_after) on the standalone send path (plugins/platforms/discord/adapter.py) to stop dropping multi-chunk messages (#44468). #44488 is the earliest-open canonical.

@liuhao1024

Copy link
Copy Markdown
Contributor Author

Closing as duplicate of #44488 by @AIalliAI, which implements the same Discord 429 retry fix (honoring retry_after in the standalone send path). That PR was opened earlier (2026-06-11T21:25Z) with the same approach and adapter file.

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 duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/discord Discord bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: hermes send to Discord drops remaining chunks on a 429 — no retry in the standalone send path (Telegram has one)

3 participants