openclaw - ✅(Solved) Fix [Bug]: Duplicate replies for single inbound on Discord [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#63027Fetched 2026-04-09 07:59:23
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
labeled ×2cross-referenced ×1

Discord replies are duplicated for a single inbound message (e.g. sending testID gives test-1 then test-2 immediately).

Root Cause

Discord replies are duplicated for a single inbound message (e.g. sending testID gives test-1 then test-2 immediately).

Fix Action

Fixed

PR fix notes

PR #63104: fix(discord): dedupe inbound deliveries across handler instances

Description (problem / solution / changelog)

Closes #63027

Summary

  • Problem: Discord could send duplicate replies for a single inbound DM when the same inbound delivery reached more than one createDiscordMessageHandler(...) instance.
  • Why it matters: One user message could trigger two reply paths, including an extra queued follow-up reply, which matches the behavior reported in #63027 and doubles token spend.
  • What changed: Moved Discord inbound dedupe from handler-instance scope to a process-global cache, keyed by accountId + messageId, and added a regression test for duplicate delivery across distinct handler instances.
  • What did NOT change (scope boundary): This PR does not change queue semantics, provider behavior, or the upstream listener lifecycle that may cause duplicate deliveries to appear in the first place.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #63027
  • Related #N/A
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: extensions/discord/src/monitor/message-handler.ts created its inbound dedupe cache inside createDiscordMessageHandler(), so dedupe only worked within a single handler instance.
  • Missing detection / guardrail: There was no regression test covering the same Discord message.id being delivered to two distinct handler instances.
  • Contributing context (if known): Duplicate deliveries can happen when monitor/listener lifecycle overlap or reconnect paths surface the same inbound event more than once. The exact upstream trigger from the field report is still unknown, but this layer should have rejected the duplicate anyway.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/discord/src/monitor/message-handler.queue.test.ts
  • Scenario the test should lock in: Two distinct Discord handlers receive the same inbound Discord message with the same message.id, and only one processing path runs.
  • Why this is the smallest reliable guardrail: A single-handler test cannot catch this bug because the failure only appears when dedupe must span handler instances.
  • Existing test that already covers this (if any): None.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • Discord inbound messages are no longer replied to twice when the same inbound delivery is observed by more than one handler instance in the same process.
  • In queue mode: collect, users should no longer see the extra queued follow-up reply that was caused by the duplicate second processing path.

Diagram (if applicable)

Before:
[one Discord inbound message]
  -> [handler A sees message.id = X] -> [reply path runs]
  -> [handler B sees message.id = X] -> [duplicate reply / queued follow-up]

After:
[one Discord inbound message]
  -> [handler A or B claims message.id = X in global dedupe cache]
  -> [reply path runs once]
  -> [duplicate delivery dropped]

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: local reproduction on macOS; original issue report says Linux
  • Runtime/container: Node v25.3.0, pnpm 10.32.1
  • Model/provider: Not provider-specific; reproduced with mocked Discord inbound processing
  • Integration/channel (if any): Discord DM
  • Relevant config (redacted): Discord auto-reply enabled; queue mode collect

Steps

  1. Create two distinct createDiscordMessageHandler(...) instances.
  2. Deliver the same inbound Discord event with the same message.id to both handlers.
  3. Observe whether the message is processed once or twice.

Expected

  • One inbound Discord message.id should be processed once per process.

Actual

  • Before this fix, the same inbound Discord message.id was processed twice when it reached two handler instances, which could surface as a duplicate queued follow-up reply.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Before fix:

  • New regression scenario failed locally because one inbound Discord message id triggered processDiscordMessageMock 2 times instead of the expected 1 time.

After fix:

  • pnpm test extensions/discord/src/monitor/message-handler.queue.test.ts

    • Test Files: 1 passed (1)
    • Tests: 16 passed (16)
  • pnpm test extensions/discord/src/monitor/message-handler.process.test.ts

    • Test Files: 1 passed (1)
    • Tests: 28 passed (28)
  • pnpm test extensions/discord/src/monitor/monitor.test.ts

    • Test Files: 1 passed (1)
    • Tests: 22 passed (22)
  • pnpm test:extension discord

    • Test Files: 112 passed (112)
    • Tests: 929 passed (929)

Human Verification (required)

  • Verified scenarios: Added and ran a regression test for duplicate delivery across distinct handler instances; reran the touched Discord handler/monitor test files; ran the recommended extension lane pnpm test:extension discord.
  • Edge cases checked: Duplicate delivery within one handler instance; duplicate delivery across distinct handler instances; global dedupe state reset between tests so test isolation stays intact.
  • What you did not verify: Live Discord DM behavior against a real account; Linux-specific runtime behavior; the exact upstream source of duplicate deliveries in the field; full-repo pnpm build && pnpm check && pnpm test.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: A process-global dedupe cache could suppress intentional reprocessing if the exact same Discord message.id were somehow replayed inside the TTL window.

    • Mitigation: Discord message ids are globally unique snowflakes, and the correct behavior for a single inbound message id is exactly-once processing per process. The cache is also bounded by TTL and accountId.
  • Risk: A shared dedupe cache can leak across tests and create false positives.

    • Mitigation: Added __resetDiscordInboundDedupeForTest() and wired it into test helpers so each test starts from a clean dedupe state.

AI Assistance

Made with Codex

Changed files

  • extensions/discord/src/monitor.tool-result.test-helpers.ts (modified, +5/-1)
  • extensions/discord/src/monitor/inbound-worker.ts (modified, +7/-2)
  • extensions/discord/src/monitor/message-handler.module-test-helpers.ts (modified, +11/-3)
  • extensions/discord/src/monitor/message-handler.queue.test.ts (modified, +35/-0)
  • extensions/discord/src/monitor/message-handler.ts (modified, +33/-11)

Code Example

https://github.com/user-attachments/assets/baf286d9-9643-4c23-9755-032c9e28d36a
https://github.com/user-attachments/assets/5476cbfe-fa60-4cf1-819a-be3a1156ba4c
https://github.com/user-attachments/assets/836d0c28-6864-42b0-b1c0-e8fe92bb3572
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Beta release blocker

No

Summary

Discord replies are duplicated for a single inbound message (e.g. sending testID gives test-1 then test-2 immediately).

Steps to reproduce

  1. In Discord thread/channel, send one message (idtest) mentioning bot as needed.
  2. Observe two assistant replies in quick succession (test-1, test-2) for one inbound user message.

Expected behavior

One inbound message => one assistant response.

Actual behavior

One inbound message => two responses from same assistant.

OpenClaw version

OpenClaw: 2026.4.8 (9ece252)

Operating system

linux 6.11.11-valve26-1-neptune-611-gb3afa9aa9ae7 (x64)

Install method

npm

Model

openai-codex/gpt-5.4

Provider / routing chain

discord (DM, account: sentinel) -> OpenClaw gateway auto-reply pipeline (queue mode: collect) -> discord (same DM conversation)

Additional provider/model setup details

  • Gateway: local loopback ws://127.0.0.1:18789
  • Runtime: running, RPC probe: ok
  • Service: systemd user service

Logs, screenshots, and evidence

https://github.com/user-attachments/assets/baf286d9-9643-4c23-9755-032c9e28d36a
https://github.com/user-attachments/assets/5476cbfe-fa60-4cf1-819a-be3a1156ba4c
https://github.com/user-attachments/assets/836d0c28-6864-42b0-b1c0-e8fe92bb3572

Impact and severity

Affected : Discord channels Severity : high Frequency : Always Consequence : double cost on token usage

Additional information

  • Earlier analysis suggested replay from queue/backlog path ([Queued messages while agent was busy]) without strict dedupe in this path.
  • Capturing filtered logs was difficult (very noisy / sparse depending on filter), but issue is consistent at runtime.

What I already verified

  • Queue mode in session: collect (debounce=1000ms, cap=20, drop=summarize)
  • Not an obvious double-gateway process:
  • openclaw parent + openclaw-gateway child (normal parent/child)
  • Duplicate persists even after update to 2026.4.8
  • Restarting gateway can temporarily affect behavior, but duplicate replies return

Additionnal notes

Issue has been going on and off for a month, but now it's every message since a new session started 2026/04/04 with New session started · model: openai-codex/gpt-5.3-codex (default: nvidia/moonshotai/kimi-k2.5) (switched to openai-codex/gpt-5.4 but didn't fix either)

extent analysis

TL;DR

The most likely fix is to implement strict deduplication in the queue/backlog path to prevent replay of messages.

Guidance

  • Review the queue mode configuration (collect with debounce=1000ms, cap=20, drop=summarize) to ensure it is not causing duplicate messages to be processed.
  • Investigate the openclaw-gateway child process to see if it is correctly handling the queue and not introducing duplicates.
  • Consider adding logging to capture more detailed information about the queue and message processing to help identify the root cause.
  • Verify that the issue persists when using a different model or provider to isolate if the problem is specific to openai-codex/gpt-5.4 or the Discord provider.

Example

No specific code snippet can be provided without more information about the implementation, but an example of how to implement deduplication in a queue might involve using a unique message ID and checking for its presence before processing a message.

Notes

The issue has been ongoing for a month and has changed behavior over time, which may indicate a complex root cause. The fact that restarting the gateway can temporarily affect the behavior suggests that there may be a timing or synchronization issue at play.

Recommendation

Apply a workaround by implementing strict deduplication in the queue/backlog path, as this is the most likely cause of the duplicate replies. This can help mitigate the issue until a more permanent fix can be found.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

One inbound message => one assistant response.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING