Skip to content

Discord: fix chunk delivery order for long messages#32819

Closed
haosenwang1018 wants to merge 1 commit intoopenclaw:mainfrom
haosenwang1018:fix/discord-chunk-order
Closed

Discord: fix chunk delivery order for long messages#32819
haosenwang1018 wants to merge 1 commit intoopenclaw:mainfrom
haosenwang1018:fix/discord-chunk-order

Conversation

@haosenwang1018
Copy link
Copy Markdown
Contributor

Summary

  • Problem: When Discord splits long messages into chunks (due to 2000 char limit), chunks sometimes arrive in reverse order (Bug: Discord message chunks delivered in reverse order #32743)
  • Why it matters: Users see garbled message ordering making bot replies hard to follow
  • What changed: deliverDiscordReply now pre-resolves the channel ID and retry runner once, then sends each text chunk directly via sendDiscordText instead of routing through the full sendMessageDiscord pipeline per chunk. This eliminates per-chunk overhead (channel-type GET, recipient re-resolution, re-chunking, client creation) that caused ordering issues under RequestClient queue contention or rate limiting.
  • What did NOT change (scope boundary): Webhook delivery path, media/voice delivery, the sendMessageDiscord function itself, and the sendDiscordText internal implementation are all untouched. The fallback to sendMessageDiscord remains for cases where rest is not provided (e.g., CLI/outbound sends).

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Integrations

Linked Issue/PR

User-visible / Behavior Changes

Discord message chunks now arrive in the correct sequential order when a long reply is split into multiple messages.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No (fewer network calls per chunk — removed redundant channel-type GET)
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • Channel: Discord
  • Config: default chunk settings (textChunkLimit: 2000, maxLinesPerMessage: 17)

Steps

  1. Have an agent reply with a message that exceeds 2000 chars or 17 lines
  2. Observe the order of chunks in Discord

Expected

  • Chunks arrive in correct sequential order (part 1, part 2, ...)

Actual

  • Before fix: chunks sometimes arrived in reverse order
  • After fix: chunks arrive in correct order

Evidence

  • Failing test/log before + passing after
    • New test sends text chunks in order via sendDiscordText when rest is provided verifies chunk ordering
    • New test falls back to sendMessageDiscord when rest is not provided verifies fallback path
    • All 457 existing Discord tests pass unchanged

Human Verification (required)

  • Verified scenarios: All 11 reply-delivery tests pass, all 457 Discord tests pass
  • Edge cases checked: webhook path (unchanged), voice path with text follow-up, fallback when rest not provided, replyToMode=first with chunks
  • What you did not verify: Live Discord environment testing (needs real bot token + rate limiting conditions)

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert the commit; the fallback to sendMessageDiscord is still present when rest is not provided
  • Files/config to restore: src/discord/monitor/reply-delivery.ts
  • Known bad symptoms reviewers should watch for: Chunks not being delivered at all (would indicate the sendDiscordText mock path has a type mismatch)

Risks and Mitigations

  • Risk: sendDiscordText does not perform forum/media channel detection (which sendMessageDiscord does via resolveDiscordChannelType)
    • Mitigation: The Discord monitor reply path always targets regular text channels or threads, never forum channels. Forum posting uses a separate code path in sendMessageDiscord for outbound sends.

When delivering chunked Discord replies, bypass sendMessageDiscord for the
bot-send path and call sendDiscordText directly with a pre-resolved channel
ID and retry runner. This eliminates per-chunk overhead (channel-type GET
request, recipient resolution, re-chunking, client creation) that caused
ordering issues under RequestClient queue contention or rate limiting.

Fixes openclaw#32743
@openclaw-barnacle openclaw-barnacle bot added channel: discord Channel integration: discord size: S labels Mar 3, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR fixes Discord chunk delivery ordering by pre-resolving the channel ID and retry runner once in deliverDiscordReply, then routing each pre-chunked text fragment directly through sendDiscordText instead of the full sendMessageDiscord pipeline. This eliminates redundant per-chunk work (channel-type GET, recipient re-resolution, re-chunking, client creation) that could cause ordering issues under RequestClient queue contention or rate limiting.

Key observations:

  • The new fast-path (sendDiscordText direct call) is correctly gated on all three of channelId, request, and rest, so the existing fallback to sendMessageDiscord is preserved for callers that don't supply a rest client.
  • The webhook delivery path is unaffected — it returns early before the new branch is reached.
  • sendDiscordText internally calls buildDiscordTextChunks again on text that is already pre-chunked by deliverDiscordReply. In practice this is a no-op (pre-chunks are always ≤ the 2000-char default), but it is redundant work.

Confidence Score: 4/5

  • Safe to merge; the fix correctly addresses the ordering issue with a focused change and preserves all existing fallback paths.
  • The approach is sound and well-tested: 457 existing tests pass, two new tests cover the happy path and fallback, and the webhook/voice paths are unchanged. The only actionable finding is a minor style optimization in reply-delivery.ts where the retry runner is unnecessarily allocated when rest is not provided—though this has no functional impact, fixing it would improve code clarity.
  • src/discord/monitor/reply-delivery.ts (lines 200-202) — consider checking params.rest when creating the retry runner.

Last reviewed commit: 3f58840

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +200 to +202
const request: RetryRunner | undefined = channelId
? createDiscordRetryRunner({})
: undefined;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The retry runner is created whenever channelId resolves, but it is only consumed in sendDiscordChunkWithFallback when both params.request and params.rest are provided (line 117). When params.rest is undefined, the runner is allocated but never used. Consider checking params.rest to avoid unnecessary allocation:

Suggested change
const request: RetryRunner | undefined = channelId
? createDiscordRetryRunner({})
: undefined;
const request: RetryRunner | undefined = channelId && params.rest
? createDiscordRetryRunner({})
: undefined;
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/discord/monitor/reply-delivery.ts
Line: 200-202

Comment:
The retry runner is created whenever `channelId` resolves, but it is only consumed in `sendDiscordChunkWithFallback` when both `params.request` and `params.rest` are provided (line 117). When `params.rest` is undefined, the runner is allocated but never used. Consider checking `params.rest` to avoid unnecessary allocation:

```suggestion
  const request: RetryRunner | undefined = channelId && params.rest
    ? createDiscordRetryRunner({})
    : undefined;
```

How can I resolve this? If you propose a fix, please make it concise.

@thewilloftheshadow
Copy link
Copy Markdown
Member

Superseded by #33226 (combined Discord chunk ordering + retry fixes).

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

Labels

channel: discord Channel integration: discord size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Discord message chunks delivered in reverse order

2 participants