Skip to content

fix: Discord read/search timeout, session-key fallback, and gateway execution mode#73521

Merged
amknight merged 4 commits intomainfrom
ak/discord-read-timeout
Apr 28, 2026
Merged

fix: Discord read/search timeout, session-key fallback, and gateway execution mode#73521
amknight merged 4 commits intomainfrom
ak/discord-read-timeout

Conversation

@amknight
Copy link
Copy Markdown
Member

Summary

Fixes #73431 — Discord message read and message search hang indefinitely, and Discord inbound message_received / inbound_claim hooks do not fire when SessionKey is empty.

Three targeted fixes, no feature creep:

1. REST timeout on Discord read/search (extensions/discord/src/send.messages.ts)

readMessagesDiscord and searchMessagesDiscord awaited rest.get(...) with no timeout or abort signal. If the Discord API hung or was slow, the CLI hung forever with empty stdout.

Added a 15-second withRestTimeout wrapper that races the promise against a timer and rejects with a structured error message.

2. Session-key fallback for inbound hooks (src/auto-reply/reply/dispatch-from-config.ts)

The internal message:received hook (line 722) is gated on sessionKey being truthy. The session key was read as ctx.SessionKey with no fallback — but Discord's SessionKey derivation can yield empty in edge cases (DMs, misconfigured channels, missing thread context).

Now falls back to ctx.CommandTargetSessionKey via normalizeOptionalString, matching the pattern already used by resolveSessionStoreLookup in the same file. This restores the intent of the closed-but-never-landed PR #33038.

3. resolveExecutionMode on Discord channel actions (extensions/discord/src/channel-actions.ts)

Discord did not define resolveExecutionMode, so all actions defaulted to "local" execution — bypassing the gateway's 10-second action timeout that Telegram gets automatically. Now routes read and search through "gateway" mode for defense-in-depth.

Testing

Diff stats

5 files changed, 72 insertions(+), 3 deletions(-)

Supersedes the approach in #61572 which added ~1000 lines of tangential feature work (compact/raw detail modes, breaking legacy parameter changes) without addressing either root cause.

…xecution mode

- Add 15s timeout to readMessagesDiscord and searchMessagesDiscord so they
  fail fast instead of hanging indefinitely (#73431)
- Fall back to CommandTargetSessionKey in dispatchReplyFromConfig when
  SessionKey is empty, so Discord inbound message:received hooks fire
  reliably (#73431, refs #33038)
- Add resolveExecutionMode to Discord channel actions routing read/search
  through gateway timeout path, matching Telegram's pattern (#73431)
@amknight amknight added bug Something isn't working regression Behavior that previously worked and now fails labels Apr 28, 2026
@openclaw-barnacle openclaw-barnacle Bot added channel: discord Channel integration: discord size: S maintainer Maintainer-authored PR labels Apr 28, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

Three targeted bug fixes: a 15 s REST timeout guard on Discord read/search to prevent indefinite hangs, a CommandTargetSessionKey fallback in dispatch-from-config.ts so the message:received internal hook fires when SessionKey is empty, and resolveExecutionMode on discordMessageActions so read/search route through gateway mode (consistent with the Telegram adapter). Changes are minimal, well-tested, and follow existing patterns in the codebase.

Confidence Score: 4/5

Safe to merge; only P2 style feedback remains.

No logic or correctness issues found. The single P2 note (real timers in hang-rejection tests adding ~30 s to CI) does not affect production behavior. Score is 4 per the P2-only ceiling.

No files require special attention.

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/discord/src/send.messages.test.ts
Line: 27-34

Comment:
**Slow timeout tests use real timers**

Both hang-rejection tests use a real `setTimeout` (15 s) and set the Vitest timeout to `DISCORD_REST_ACTION_TIMEOUT_MS + 5_000` = 20 s each. This adds ~30 s to every CI run for two tests. Using `vi.useFakeTimers()` / `vi.runAllTimersAsync()` would make them instant and remove the large explicit timeout overrides.

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

Reviews (1): Last reviewed commit: "fix: Discord read/search timeout, sessio..." | Re-trigger Greptile

Comment on lines +27 to +34
async () => {
restMock.get.mockReturnValueOnce(new Promise(() => {}));

await expect(readMessagesDiscord("C1", {}, { cfg: {} as never })).rejects.toThrow(
/Discord read timed out/,
);
},
DISCORD_REST_ACTION_TIMEOUT_MS + 5_000,
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.

P2 Slow timeout tests use real timers

Both hang-rejection tests use a real setTimeout (15 s) and set the Vitest timeout to DISCORD_REST_ACTION_TIMEOUT_MS + 5_000 = 20 s each. This adds ~30 s to every CI run for two tests. Using vi.useFakeTimers() / vi.runAllTimersAsync() would make them instant and remove the large explicit timeout overrides.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/discord/src/send.messages.test.ts
Line: 27-34

Comment:
**Slow timeout tests use real timers**

Both hang-rejection tests use a real `setTimeout` (15 s) and set the Vitest timeout to `DISCORD_REST_ACTION_TIMEOUT_MS + 5_000` = 20 s each. This adds ~30 s to every CI run for two tests. Using `vi.useFakeTimers()` / `vi.runAllTimersAsync()` would make them instant and remove the large explicit timeout overrides.

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

Inject AbortSignal.timeout into the Discord proxy-request-client fetch
wrapper so every Discord REST call gets a 15s timeout at the HTTP level.
This replaces the Promise.race wrapper in send.messages.ts — cleaner,
covers all calls, and actually aborts the TCP connection.
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 28, 2026

Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve.

Keep this PR open. It is maintainer-authored/protected (authorAssociation: MEMBER and maintainer label), and current main still lacks the PR's intended Discord gateway routing, REST timeout, and CommandTargetSessionKey fallback for internal message hooks.

Best possible solution:

Keep this PR open for maintainer review. The best path is to revise or land the focused Discord regression fix for #73431, or explicitly supersede it with another PR that adds the same three pieces: Discord read/search timeout, gateway execution routing for read/search, and CommandTargetSessionKey fallback for internal inbound hooks.

What I checked:

Remaining risk / open question:

  • The PR's timeout regression test shown in the provided diff uses the real 15-second timeout path, which may slow CI unless fake timers or an injectable timeout are used.
  • The provided PR diff's fetch wrapper replaces any caller-provided RequestInit.signal with a timeout signal; maintainers should confirm no Discord REST caller relies on its own abort signal or merge the signals before landing.
  • No live Discord verification is included in the provided PR context; the support is source-level and unit-test oriented for the reported failure modes.

Codex review notes: model gpt-5.5, reasoning high; reviewed against c478aeca5a7f.

@amknight amknight merged commit e4ff7c1 into main Apr 28, 2026
67 checks passed
@amknight amknight deleted the ak/discord-read-timeout branch April 28, 2026 11:46
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…xecution mode (openclaw#73521)

* fix: Discord read/search timeout, session-key fallback, and gateway execution mode

- Add 15s timeout to readMessagesDiscord and searchMessagesDiscord so they
  fail fast instead of hanging indefinitely (openclaw#73431)
- Fall back to CommandTargetSessionKey in dispatchReplyFromConfig when
  SessionKey is empty, so Discord inbound message:received hooks fire
  reliably (openclaw#73431, refs openclaw#33038)
- Add resolveExecutionMode to Discord channel actions routing read/search
  through gateway timeout path, matching Telegram's pattern (openclaw#73431)

* fix: move timeout to fetch layer, drop send.messages wrapper

Inject AbortSignal.timeout into the Discord proxy-request-client fetch
wrapper so every Discord REST call gets a 15s timeout at the HTTP level.
This replaces the Promise.race wrapper in send.messages.ts — cleaner,
covers all calls, and actually aborts the TCP connection.

* fix: remove unused callerController variable in proxy-request-client test

* fix: remove unnecessary mergeAbortSignal helper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working channel: discord Channel integration: discord maintainer Maintainer-authored PR regression Behavior that previously worked and now fails size: S

Projects

None yet

1 participant