Skip to content

[Bug]: Discord chunked send drops chunks silently on transient errors (regression in 2026.5.12 via sendDurableMessageBatch) #82858

Description

@Piste

[Bug]: Discord chunked send drops chunks silently on transient errors (regression in 2026.5.12 via sendDurableMessageBatch)

Related (closed-as-not-planned): #32887

TL;DR

After upgrading from [email protected][email protected] (with @openclaw/[email protected]), long agent replies that are correctly split into multiple Discord chunks by the chunker only have chunk 1 delivered to Discord. Chunks 2+ silently never appear. No 429/5xx error is logged. The transcript stored in the session jsonl shows the full reply.

This is the same symptom class as #32887 (which targeted the old sendMessageDiscord path), but in the new sendDurableMessageBatch delivery wrapper introduced in 2026.5.12. #32887 was stale-closed; this looks like a fresh recurrence in a different code path.

Reproduction

  1. On openclaw 2026.5.12 + @openclaw/discord 2026.5.12, with any agent backed by a model that produces multi-paragraph replies (Codex/gpt-5.5 in my case).
  2. Send the agent a prompt that elicits a >2000 char or >17 line response into a Discord DM (e.g. "Brainstorm 5 ways you could be more proactive — explain each in 2-3 sentences").
  3. Observe: Discord receives only the first chunk. No follow-up message, no error.

Concrete observed case

  • Session: Discord DM (agent:main:discord:default:direct:...)
  • Model output: 2,060 chars, 30 lines
  • Chunker (verified by extracting and running it standalone on the actual text):
    • Produces 2 chunks: 1,049 chars / 17 lines and 1,010 chars / 13 lines
  • Discord channel: only chunk 1 delivered. No chunk 2.
  • Gateway journal at the send timestamp: no rate-limit, no HTTP error, no partial_failed, no Discord send failed. Only side-effect logs:
    [plugins] [aight-utils] agent_end fired session=...
    [plugins] [aight-utils] Push sent: ... ok=true   (x2 mobile devices)
    
    (mobile push notifications fired ok — those are a separate aight-utils plugin, not the Discord channel post)

Regression bisect

Diffed @openclaw/discord dist/ between 2026.5.7 (works) and 2026.5.12 (broken):

  • buildDiscordTextChunks()identical
  • chunkDiscordTextWithMode() / chunkDiscordText()identical (constants DEFAULT_MAX_CHARS=2000, DEFAULT_MAX_LINES=17 unchanged)
  • sendDiscordText()identical body (loops over chunks calling sendChunkrequest(() => createChannelMessage(...)))
  • deliverDiscordReply() — changed:
    • 2026.5.7: await deliverOutboundPayloads({ payloads, ... }) — simple list of results
    • 2026.5.12: await sendDurableMessageBatch({ payloads, ... }) — new durable wrapper with {status, results, error} shape, including a partial_failed branch that throws

The new sendDurableMessageBatch is in openclaw/dist/send-BvX1IpyO.js (lines ~168+). It goes through withDurableMessageSendContextctx.render()ctx.send()deliverOutboundPayloadsInternal(). Somewhere on this path, chunks 2+ appear to be dropped before reaching the per-chunk HTTP call, with no error surfaced at INFO level.

I didn't have time to instrument deliverOutboundPayloadsInternal directly to pinpoint the drop. My guess (untested): the rendered batch plan treats the multi-chunk payload as a single rendered unit, or onPayloadDeliveryOutcome only fires for the first payload before something short-circuits the rest.

Local workaround applied

Patched send.shared-*.js's sendDiscordText to wrap each per-chunk sendChunk() in a retry-with-backoff (3 attempts, honors retry-after, retries 429 + 5xx), AND to continue best-effort if a single chunk permanently fails (logs the failure loudly instead of throwing silently). This restores end-to-end multi-chunk delivery for the symptom but does not fix the underlying drop in the durable wrapper.

Patch is reapplied by a small post-openclaw update hook since plugin reinstall otherwise clobbers it.

Environment

  • openclaw: 2026.5.12
  • @openclaw/discord: 2026.5.12
  • Model: openai-codex/gpt-5.5 (ChatGPT Pro via OAuth)
  • OS: Linux (Debian-based VM)
  • Node: v22.19.0

What would help

  • Confirmation of the drop location in deliverOutboundPayloadsInternal / the durable wrapper
  • Whether 2026.5.14-beta.* or 2026.5.16-beta.* already addresses this
  • Whether the chunk fan-out is supposed to happen at the durable-payload layer or at the channel-plugin layer (the 2026.5.7→2026.5.12 refactor seems to have moved the boundary; possibly chunks are no longer being propagated)

Filed via Claude Code on behalf of @Piste — investigation and patch authored by the AI agent against my live install. Happy to gather additional traces or test fixes against my environment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:needs-infoClawSweeper needs more reporter information before it can verify this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions