Skip to content

fix(discord): notify user on discord when inbound worker times out.#40819

Closed
Kimbo7870 wants to merge 4 commits intoopenclaw:mainfrom
Kimbo7870:fix/discord-timeout-user-feedback-message-fix
Closed

fix(discord): notify user on discord when inbound worker times out.#40819
Kimbo7870 wants to merge 4 commits intoopenclaw:mainfrom
Kimbo7870:fix/discord-timeout-user-feedback-message-fix

Conversation

@Kimbo7870
Copy link
Copy Markdown
Contributor

@Kimbo7870 Kimbo7870 commented Mar 9, 2026

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: When channels.discord.inboundWorker.runTimeoutMS is set to a time that's smaller than agents.defaults.timeoutSeconds, and the time expires while a model is processing, it times out without notifying the user on Discord.
  • Why it matters: Normally, for other timeout situations, the user still gets a visible message on Discord. But in this case, the user does not get a visible message on Discord. So if someone is not watching logs, the bot just appears frozen and they do not know OpenClaw already stopped processing.
  • What changed: The Discord inbound worker now sends a user-visible timeout reply through the normal Discord reply delivery path, and it suppresses that fallback if a final reply has already started or already gone out.
  • What did NOT change (scope boundary): This does not change agent/model timeout behavior, timeout defaults, or non-Discord channels.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Gateway / orchestration
  • Integrations

User-visible / Behavior Changes

Discord users now receive a timeout reply when the Discord inbound worker times out before a final response is delivered.
The timeout reply is: Discord inbound worker timed out.

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) Yes
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation: The worker-timeout path now sends one outbound Discord reply when no final reply has already started. It reuses the existing Discord reply delivery path and resolved reply target, including auto-thread targets, and suppresses the fallback once final reply delivery has started.

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: Node 22, pnpm
  • Model/provider: local Ollama model for manual repro
  • Integration/channel (if any): Discord

Steps

  1. Configure a Discord bot account with a model. I used a bigger model from Ollama locally that takes some time to run.
  2. In openclaw.json, either set agents.defaults.timeoutSeconds to something larger than 1800, because channels.discord.inboundWorker.runTimeoutMS defaults to 30 minutes, or set channels.discord.inboundWorker.runTimeoutMS to something smaller like 25000 and agents.defaults.timeoutSeconds to something bigger like 35 for quicker testing.
  3. Make sure channels.discord.inboundWorker.runTimeoutMS < agents.defaults.timeoutSeconds (besides 0), then send a prompt on Discord that takes longer than channels.discord.inboundWorker.runTimeoutMS to finish.
  4. Before this fix, you can verify the timeout with openclaw logs --follow, ollama serve, or anything else that shows the model is still running, because you will see timeout logs but no message on Discord.

Expected

  • The user receives a message in Discord indicating the request timed out.

Actual

  • OpenClaw logs show discord inbound worker timed out after... but no corresponding Discord message is sent to the user.

Evidence

1_min_evidence_openclaw.mov

Attach at least one:

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

Human Verification (required)

What you personally verified (not just CI), and how:

Verified scenarios:

  • I manually tested this pre-fix and post-fix with time values ranging from 0 seconds to hours to make sure the Discord bot really was not sending a message before, and that it now does send one after the timeout.
  • I ran pnpm exec vitest run src/discord/monitor/message-handler.queue.test.ts and pnpm build.

Edge cases checked:

  • Edge case where runTimeoutMs is 0, message stays properly disabled.
  • Only one timeout message is sent per discord message.
  • No timeout fallback is sent once final reply delivery has already started or already completed.
  • The timeout fallback follows the resolved Discord reply target, including created auto-threads.

What you did not verify:

  • Multiple Discord bots running at the same time.

Compatibility / Migration

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

Failure Recovery (if this breaks)

  • Files/config to restore:
    • src/discord/monitor/inbound-worker.ts
    • src/discord/monitor/message-handler.process.ts
    • src/discord/monitor/message-handler.queue.test.ts

AI-assisted PR, gpt-5.4

Human Testing Level:
[ x ] moderately tested

I reviewed the generated changes and understand what the code does.

@openclaw-barnacle openclaw-barnacle bot added channel: discord Channel integration: discord size: M labels Mar 9, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 9, 2026

Greptile Summary

This PR fixes a UX gap where Discord users received no feedback when the channels.discord.inboundWorker.runTimeoutMS deadline expired while the model was still processing. The fix introduces an optional observer pattern on processDiscordMessage to surface three lifecycle events (onFinalReplyStart, onFinalReplyDelivered, onReplyPlanResolved) to the caller, which are then used in processDiscordInboundJob to decide whether a fallback timeout reply should be sent.

Key changes:

  • inbound-worker.ts: On worker timeout, a "Discord inbound worker timed out." error reply is delivered via the existing deliverDiscordReply path, routed to the correct channel or auto-created thread. The fallback is suppressed if onFinalReplyStart or onFinalReplyDelivered has already fired.
  • message-handler.process.ts: Adds the optional DiscordMessageProcessObserver interface and hooks (notifyFinalReplyStart is idempotent and called before each final-reply delivery await; onReplyPlanResolved is called right after the reply plan resolves, early enough to capture a just-created auto-thread ID).
  • message-handler.queue.test.ts: Four new focused tests verify the happy path, suppression when the reply is complete, suppression when the reply is in flight, and auto-thread routing.

The implementation is clean, well-scoped, and the logic is correct. The rest field intentionally omitted from the timeout reply's deliverDiscordReply call is acceptable since token-based delivery is the fallback path and rest is an optional parameter. The fire-and-forget (void) dispatch of the timeout reply is appropriate because error handling is contained within sendDiscordInboundWorkerTimeoutReply and the timeout callback must be synchronous.

Confidence Score: 4/5

  • This PR is safe to merge — it is a well-scoped, additive bug fix with no breaking changes to existing call sites.
  • The logic is correct: the finalReplyStarted gate reliably prevents double-sends because notifyFinalReplyStart() is always called synchronously before any final-reply await, while the timeout fires as a macrotask and cannot interleave with in-progress synchronous code. The observer is optional, so no existing callers are affected. The four new tests cover the primary scenarios (basic fallback, already-delivered suppression, in-flight suppression, auto-thread routing). One point deducted for the absence of a test covering the case where onReplyPlanResolved is never called (i.e., timeout before resolveDiscordAutoThreadReplyPlan resolves), though the fallback to messageChannelId handles it correctly in production.
  • No files require special attention.

Last reviewed commit: 41cae55

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 41cae55749

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@Kimbo7870 Kimbo7870 changed the title Fix/discord timeout user feedback message fix fix(discord): notify user on discord when inbound worker times out. Mar 9, 2026
@dutifulbob
Copy link
Copy Markdown
Contributor

dutifulbob commented Mar 24, 2026

Triage result

Quick read

  • Intent valid: ✅ Yes
  • Solves the right problem: ✅ Yes, mostly
  • Refactor needed: 🔧 Superficial
  • Human attention: 🟢 Not required
  • Recommendation: 🏁 continue autonomously

Intent

This PR is trying to make Discord stop feeling frozen when the inbound worker times out. In plain English: if OpenClaw gives up on a long-running Discord request, the user should see an actual timeout message in Discord instead of silence.

Why

  • The intention is good and user-facing. The timeout already happens; this PR is about making that failure visible instead of forcing people to infer it from logs.
  • The core idea is right: reuse the normal Discord reply path so the timeout notice goes back to the same place the real reply would have gone, and suppress the fallback once final reply delivery has already started.
  • This does not look like a fundamental redesign problem. The main issue is that the PR is stale against current main.
  • The repo has since moved this Discord surface from src/discord/... to extensions/discord/..., and GitHub shows this PR as dirty / conflicting. So the work needs a straightforward port or rebase onto the current Discord extension files, not a human-level reframing of the feature.
  • I do not think this needs product or architecture judgment before moving forward. It looks like an ordinary update-and-retest job.

AI review

  • Status: ✅ Clear of remaining P0/P1 blockers
  • Notes: This PR has already gone through AI review. The Codex review raised one ordering concern: if the timeout fallback send is fire-and-forget, a newer reply could appear before the older timeout notice. That was a valid comment, and the later commit changed the worker timeout path to await the fallback send before finishing the run. I do not see any remaining P0 or P1 AI findings on the PR as it stands.

CI/CD

  • Status: ⏸️ Historical run was green, but the branch is now stale
  • Notes: The historical CI run on this PR was green. But that is not enough to call it merge-ready today, because the branch is now conflicting with current main. The old CI result is a good sign for the original change, but it is stale as a landing signal.

Recommendation

🏁 continue autonomously

What I would do next is:

  1. port this change onto the current extensions/discord/... files
  2. rerun AI review on the updated PR head
  3. rerun CI on the rebased branch

If that updated branch stays as scoped as this one, I would not send it back for human attention just because of the repo drift.

@dutifulbob
Copy link
Copy Markdown
Contributor

I rebased this fix locally onto current main, validated it, and published the updated branch as a replacement PR because this account cannot push to the original fork branch directly.

Replacement PR:
#53823

What changed in the replacement:

  • ports the fix from the old src/discord/... surface onto the current extensions/discord/... files
  • keeps the visible timeout reply behavior
  • keeps created auto-thread routing for the fallback reply
  • properly preserves queue ordering by making the worker timeout helper await async timeout cleanup before the next queued run starts

Validation run on the rebased branch:

  • pnpm test -- extensions/discord/src/monitor/message-handler.queue.test.ts extensions/discord/src/monitor/message-handler.bot-self-filter.test.ts
  • pnpm build

@dutifulbob
Copy link
Copy Markdown
Contributor

dutifulbob commented Mar 24, 2026

I had to recreate this on a branch I can actually update.

Replacement PR: #53823
#53823

That replacement keeps the same contributor-authored commits and author info on top of current main:

  • 684ca2d fix(discord): notify user on discord when inbound worker times out.
  • 80062f6 fix(discord): notify user on discord when inbound worker times out.
  • e5c389d Discord: await timeout fallback reply

I do not have permission to close #40819 from this account, so the PR itself still has to be closed by someone with write access.

@osolmaz osolmaz closed this Mar 24, 2026
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: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants